diff --git a/user-crypto/miv-rv32-aes-cryptography/.cproject b/user-crypto/miv-rv32-aes-cryptography/.cproject
new file mode 100644
index 0000000..a4390e1
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/.cproject
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/.gitignore b/user-crypto/miv-rv32-aes-cryptography/.gitignore
new file mode 100644
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/.project b/user-crypto/miv-rv32-aes-cryptography/.project
new file mode 100644
index 0000000..711a87e
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-aes-cryptography
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/README.md b/user-crypto/miv-rv32-aes-cryptography/README.md
new file mode 100644
index 0000000..323fd24
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/README.md
@@ -0,0 +1,158 @@
+PolarFire User Crypto AES Cryptography Services example
+================================================================================
+This example project demonstrate the use of symmetric key encryption and
+decryption services. The following PolarFire User Crypto service functions are used
+
+ - CALSymEncrypt()
+ - CALSymEncryptDMA()
+ - CALSymDecrypt()
+ - CALSymDecryptDMA()
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal followed by a menu system and instructions.
+
+This program displays the return data from User Crypto processor for encryption
+and decryption services.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Data Encryption
+
+Select option '1' for data encryption using AES-256 algorithm based on electronic
+code book encryption (ECB) mode and key. This example project reads the plain
+text and an encryption key from URAT terminal and calls **CALSymEncrypt()** or
+**CALSymEncryptDMA()** function. The **CALSymEncrypt()** and **CALSymEncryptDMA()**
+functions encrypt the message based on electronic code book encryption (ECB)
+mode and symmetric encryption key and generate the cipher text. This cipher
+text is also displayed on UART terminal.
+
+### Data Decryption
+
+Select option '2' for data decryption using AES-256 algorithm based on electronic
+code book (ECB) mode and key. This example project reads a cipher text and a
+decryption key from URAT terminal and calls **CALSymDecrypt()** or **CALSymDecrypt()**
+function. The **CALSymDecrypt()** and **CALSymDecryptDMA()** functions decrypt the
+cipher text based on ECB mode and symmetric encryption key, and generate the
+plain text. The generated plain text is also displayed on UART terminal. You
+have to provide same key to decrypt the cipher text, which is used for encryption.
+
+**NOTE:**
+ If you try to enter data values other than 0 - 9, a - f, A - F, an error
+ message will be displayed on the serial port terminal.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality. You can use
+RV32_AES_Cryptography.ttl Tera Term Macro script present in project directory for
+testing AES Cryptography example project.
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/RV32_AES_Cryptography.ttl b/user-crypto/miv-rv32-aes-cryptography/RV32_AES_Cryptography.ttl
new file mode 100644
index 0000000..f175060
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/RV32_AES_Cryptography.ttl
@@ -0,0 +1,246 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+changedir '.'
+logopen "AES_Cryptography.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto AES-128'
+
+setsync 1
+
+;Clear screen
+clearscreen 0
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+;; Send Dummy
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+; AES-128 Encryption
+; ---------------------------------------------------------------------------------------------------------------
+;Test Case 1 - using DMA
+; INPUT
+; COUNT = 0
+; KEY = c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558
+; PLAINTEXT = 00000000000000000000000000000000
+; OUTPUT
+; CIPHERTEXT = 46f2fb342d6f0ab477476fc501242c5f
+; ---------------------------------------------------------------------------------------------------------------
+send '1'
+pause 1
+
+;key
+send 'c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;PLAINTEXT
+send '00000000000000000000000000000000'
+send 13
+pause 1
+
+;DMA enabled
+send '1'
+pause 4
+
+;Press any key
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+;Test Case 2 - non DMA
+; INPUT
+; COUNT = 0
+; KEY = c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558
+; PLAINTEXT = 00000000000000000000000000000000
+; OUTPUT
+; CIPHERTEXT = 46f2fb342d6f0ab477476fc501242c5f
+; ---------------------------------------------------------------------------------------------------------------
+send '1'
+pause 1
+
+;key
+send 'c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;PLAINTEXT
+send '00000000000000000000000000000000'
+send 13
+pause 1
+
+;DMA disabled
+send '0'
+pause 4
+
+;Press any key
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+; Test Case 3 - DMA enabled
+; INPUT
+; KEY = 0000000000000000000000000000000000000000000000000000000000000000
+; PLAINTEXT = 91fbef2d15a97816060bee1feaa49afe
+; OUTPUT
+; CIPHERTEXT = 1bc704f1bce135ceb810341b216d7abe
+; ---------------------------------------------------------------------------------------------------------------
+send '1'
+pause 1
+
+;key
+send '0000000000000000000000000000000000000000000000000000000000000000'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;PLAINTEXT
+send '91fbef2d15a97816060bee1feaa49afe'
+send 13
+pause 1
+
+;DMA Enabled
+send '1'
+pause 4
+
+;Press any key
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+; Test Case 4 - DMA disabled
+; INPUT
+; KEY = 0000000000000000000000000000000000000000000000000000000000000000
+; PLAINTEXT = 91fbef2d15a97816060bee1feaa49afe
+; OUTPUT
+; CIPHERTEXT = 1bc704f1bce135ceb810341b216d7abe
+; ---------------------------------------------------------------------------------------------------------------
+send '1'
+pause 1
+
+;key
+send '0000000000000000000000000000000000000000000000000000000000000000'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;PLAINTEXT
+send '91fbef2d15a97816060bee1feaa49afe'
+send 13
+pause 1
+
+;DMA Disabled
+send '0'
+pause 4
+
+;Press any key
+send $0
+
+
+; ---------------------------------------------------------------------------------------------------------------
+; Test Case 5 - DMA Enabled
+; INPUT
+; KEY = 1d85a181b54cde51f0e098095b2962fdc93b51fe9b88602b3f54130bf76a5bd9
+; PLAINTEXT = 00000000000000000000000000000000
+; OUTPUT
+; CIPHERTEXT = 531c2c38344578b84d50b3c917bbb6e1
+; ---------------------------------------------------------------------------------------------------------------
+send '1'
+pause 1
+
+;key
+send '1d85a181b54cde51f0e098095b2962fdc93b51fe9b88602b3f54130bf76a5bd9'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;PLAINTEXT
+send '00000000000000000000000000000000'
+send 13
+pause 1
+
+;DMA Enabled
+send '1'
+pause 4
+
+;Press any key
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+; AES-128 Decryption
+; ---------------------------------------------------------------------------------------------------------------
+; ---------------------------------------------------------------------------------------------------------------
+; Test Case 6 - non DMA
+; INPUT
+; KEY = 28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64
+; CIPHERTEXT = 4bf3b0a69aeb6657794f2901b1440ad4
+; OUTPUT
+; PLAINTEXT = 00000000000000000000000000000000
+; ---------------------------------------------------------------------------------------------------------------
+send '2'
+pause 1
+
+;key
+send '28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;CIPHERTEXT
+send '4bf3b0a69aeb6657794f2901b1440ad4'
+pause 1
+
+;DMA disabed
+send '0'
+pause 4
+
+;Press any key
+send $0
+
+
+; ---------------------------------------------------------------------------------------------------------------
+; Test Case 7 - DMA
+; INPUT
+; KEY = 28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64
+; CIPHERTEXT = 4bf3b0a69aeb6657794f2901b1440ad4
+; OUTPUT
+; PLAINTEXT = 00000000000000000000000000000000
+; ---------------------------------------------------------------------------------------------------------------
+send '2'
+pause 1
+
+;key
+send '28d46cffa158533194214a91e712fc2b45b518076675affd910edeca5f41ac64'
+pause 1
+
+;IV
+send '00000000000000000000000000000000'
+pause 1
+
+;CIPHERTEXT
+send '4bf3b0a69aeb6657794f2901b1440ad4'
+pause 1
+
+;DMA enabed
+send '1'
+
+pause 5
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw Debug.launch b/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw Debug.launch
new file mode 100644
index 0000000..c681675
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw attach.launch b/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw attach.launch
new file mode 100644
index 0000000..199daf6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/miv-rv32-aes-cryptography hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/application/helper.c b/user-crypto/miv-rv32-aes-cryptography/src/application/helper.c
new file mode 100644
index 0000000..4a78569
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/application/helper.c
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+extern UART_instance_t g_uart;
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+)
+{
+ uint32_t inc;
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ clear_variable(src_ptr, 4);
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count%2) == 0)
+ {
+ ret_size = count/2;
+ }
+ else
+ {
+ if(size!=1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count/2)+1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ volatile uint8_t invalid_ip = 1u;
+ uint8_t dma_enable = 0;
+
+ const uint8_t invalid_ms[] = "\r\n Invalid input. ";
+
+ while(invalid_ip != 0)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(&dma_enable, 1, msg, msg_size);
+
+ if(dma_enable >= 2)
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+ else
+ {
+ invalid_ip = 0;
+ }
+ }
+
+ return dma_enable;
+}
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/application/helper.h b/user-crypto/miv-rv32-aes-cryptography/src/application/helper.h
new file mode 100644
index 0000000..7f21b6e
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/application/helper.h
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/application/main.c b/user-crypto/miv-rv32-aes-cryptography/src/application/main.c
new file mode 100644
index 0000000..30427c6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/application/main.c
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This Example Project demonstrates the usage of PolarFire User Crypto
+ * services for message encryption and decryption using AES algorithm.
+ *
+ */
+#include
+#include
+#include
+#include "stdint.h"
+#include "helper.h"
+#include "hal/hal.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+
+#define KEY_SIZE 32
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+********* PolarFire User Crypto AES Cryptography Service Example Project *********\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the PolarFire User Crypto \r\n\
+ Cryptography Services. The following User Athena services are demonstrated:\r\n\
+ 1 - AES-256 encryption.\r\n\
+ 2 - AES-256 decryption.\r\n";
+
+const uint8_t g_select_operation_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select the Cryptographic operation to perform:\r\n\
+ Press key '1' to perform AES-256 encryption \r\n\
+ Press key '2' to perform AES-256 decryption \r\n\
+------------------------------------------------------------------------------\r\n";
+static const uint8_t aes_encrypt_select_msg[] =
+"\r\n Selected AES-256 encryption service. \r\n";
+static const uint8_t aes_decrypt_select_msg[] =
+"\r\n Selected AES-256 decryption service. \r\n";
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t read_key_msg[] =
+"\r\n Enter the 256-bit/32-byte key: \r\n";
+static const uint8_t read_data_msg[] =
+"\r\n Enter the 16 bytes of input data to encrypt:\r\n";
+static const uint8_t read_iv_msg[] =
+"\r\n Enter the 16 bytes initialization vector(IV):\r\n";
+static const uint8_t read_dma_enable_ip[] =
+"\r\n Enter 1 to perform Symmetric encryption with DMA or \r\n\
+ 0 to perform Symmetric encryption without DMA: \r\n";
+static const uint8_t read_encrypted_data_msg[] =
+"\r\n Enter the 16 bytes of cipher text to decrypt: \r\n";
+
+/*==============================================================================
+ Global Variables.
+ */
+static uint8_t __attribute__ ((section (".crypto_data"))) g_cipher_text[KEY_SIZE/2] = {0x00};
+static uint8_t __attribute__ ((section (".crypto_data"))) g_key_256bit[KEY_SIZE] = {0x00};
+static uint8_t __attribute__ ((section (".crypto_data"))) g_iv[KEY_SIZE/2] = {0x00};
+static uint8_t __attribute__ ((section (".crypto_data"))) g_plain_text[KEY_SIZE] = {0x00};
+
+/*==============================================================================
+ Clear AES global variable.
+ */
+static void clear_aes_var(void)
+{
+ uint16_t var = 0;
+
+ for(var = 0; var < sizeof(g_key_256bit); var++)
+ {
+ g_key_256bit[var] = 0;
+ }
+ for(var = 0; var < sizeof(g_iv); var++)
+ {
+ g_iv[var] = 0;
+ }
+ for(var = 0; var < sizeof(g_plain_text); var++)
+ {
+ g_plain_text[var] = 0;
+ }
+ for(var = 0; var < sizeof(g_cipher_text); var++)
+ {
+ g_cipher_text[var] = 0;
+ }
+}
+
+/*==============================================================================
+ AES-256 encryption.
+ */
+static void aes256_encryption(void)
+{
+ uint8_t status = 0u;
+ uint8_t use_dma = 0;
+ uint16_t msg_len = 0;
+
+ /* Clear input and output variables */
+ clear_aes_var();
+
+ /* Get key. */
+ get_input_data(&g_key_256bit[0], sizeof(g_key_256bit), read_key_msg,
+ sizeof(read_key_msg));
+
+ /* Get Initialization Vector value */
+ get_input_data(&g_iv[0], sizeof(g_iv), read_iv_msg, sizeof(read_iv_msg));
+
+ /* Read input data to be encrypt. */
+ msg_len = get_input_data(&g_plain_text[0], sizeof(g_plain_text),
+ read_data_msg, sizeof(read_data_msg));
+
+ /* Use dma or not */
+ use_dma = enable_dma(read_dma_enable_ip, sizeof(read_dma_enable_ip));
+
+ if(use_dma != 1)
+ {
+ /* Without DMA */
+ status = CALSymEncrypt(SATSYMTYPE_AES256, (uint32_t *)&g_key_256bit[0],
+ SATSYMMODE_ECB, g_iv, SAT_TRUE, g_plain_text,
+ g_cipher_text , msg_len);
+ }
+ else
+ {
+ /* With DMA */
+ status = CALSymEncryptDMA(SATSYMTYPE_AES256, (uint32_t *)&g_key_256bit[0],
+ SATSYMMODE_ECB, g_iv, SAT_TRUE,
+ g_plain_text, g_cipher_text , msg_len,
+ X52CCR_DEFAULT);
+ }
+
+ /* Display the encrypted data. i.e. Cipher text*/
+ if(SATR_SUCCESS == status)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Encrypted data:\r\n",
+ sizeof("\r\n Encrypted data:\r\n"));
+ display_output(g_cipher_text, sizeof(g_cipher_text));
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Error\r\n",
+ sizeof("\r\n Error\r\n"));
+ }
+}
+
+/*==============================================================================
+ AES-256 decryption.
+ */
+static void aes256_decryption(void)
+{
+ uint8_t status = 0u;
+ uint8_t use_dma = 0;
+ uint16_t cipher_len = 0;
+
+
+ /* Clear input and output variables. */
+ clear_aes_var();
+
+ /* Get Key from the user to perform Decryption. Note this key should be
+ * same as that used for message encryption. */
+ get_input_data(&g_key_256bit[0], sizeof(g_key_256bit), read_key_msg,
+ sizeof(read_key_msg));
+
+ /* Get Initialization Vector value */
+ get_input_data(&g_iv[0], sizeof(g_iv), read_iv_msg, sizeof(read_iv_msg));
+
+ /* Read encrypted data i.e 16 bytes of cipher text to be decrypt. */
+ cipher_len = get_input_data(&g_cipher_text[0], sizeof(g_cipher_text),
+ read_encrypted_data_msg, sizeof(read_encrypted_data_msg));
+
+ /* Use dma or not */
+ use_dma = enable_dma(read_dma_enable_ip, sizeof(read_dma_enable_ip));
+
+ if(use_dma != 1)
+ {
+ status = CALSymDecrypt(SATSYMTYPE_AES256, (uint32_t*)&g_key_256bit[0],
+ SATSYMMODE_ECB, g_iv, SAT_TRUE, g_cipher_text,
+ g_plain_text, cipher_len);
+ }
+ else
+ {
+ status = CALSymDecryptDMA(SATSYMTYPE_AES256, (uint32_t*)&g_key_256bit[0],
+ SATSYMMODE_ECB, g_iv, SAT_TRUE, g_cipher_text,
+ g_plain_text, cipher_len,
+ X52CCR_DEFAULT);
+ }
+
+ /* Display the Decrypted data i.e. Plain text. */
+ if(SATR_SUCCESS == status)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Decrypted data:\r\n",
+ sizeof("\r\n Decrypted data:\r\n"));
+ display_output(g_plain_text, sizeof(g_plain_text));
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Error\r\n",
+ sizeof("\r\n Error\r\n"));
+ }
+}
+
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Display the choice of cryptographic operation to perform.
+ */
+static void display_operation_choices(void)
+{
+ UART_send(&g_uart, g_select_operation_msg, sizeof(g_select_operation_msg));
+}
+
+/*==============================================================================
+ Display the Option to continue.
+ */
+static void display_option(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_buff[1];
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Press any key to continue.\r\n",
+ sizeof("\r\n Press any key to continue.\r\n"));
+ do
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ } while(0u == rx_size);
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+int main( void )
+{
+ uint8_t rx_buff[1];
+ size_t rx_size = 0;
+
+
+ /* 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));
+
+ /* Initializes the Athena Processor. */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Select cryptographic operation */
+ display_operation_choices();
+
+ for(;;)
+ {
+ /* Read inputs from UART terminal. */
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ switch(rx_buff[0])
+ {
+ case '1':
+ /* Perform encryption using AES-256 */
+ UART_send(&g_uart, aes_encrypt_select_msg,
+ sizeof(aes_encrypt_select_msg));
+ aes256_encryption();
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '2':
+ /* Perform decryption using AES-256 */
+ UART_send(&g_uart, aes_decrypt_select_msg,
+ sizeof(aes_decrypt_select_msg));
+ aes256_decryption();
+ display_option();
+ display_operation_choices();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/aesf5200.h
new file mode 100644
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calcontext.h
new file mode 100644
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calenum.h
new file mode 100644
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calini.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calini.h
new file mode 100644
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calpolicy.h
new file mode 100644
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/caltypes.h
new file mode 100644
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/config_user.h
new file mode 100644
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbg.h
new file mode 100644
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbgf5200.h
new file mode 100644
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/hash.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/hash.h
new file mode 100644
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/mac.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/mac.h
new file mode 100644
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100644
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100644
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/nrbg.h
new file mode 100644
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pk.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pk.h
new file mode 100644
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkx.h
new file mode 100644
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkxlib.h
new file mode 100644
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/shaf5200.h
new file mode 100644
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/sym.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/sym.h
new file mode 100644
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/utils.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/utils.h
new file mode 100644
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/x52cfg_user.h
new file mode 100644
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/README.md b/user-crypto/miv-rv32-aes-cryptography/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/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/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-aes-cryptography/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-aes-cryptography/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/user-crypto/miv-rv32-ccm-services/.cproject b/user-crypto/miv-rv32-ccm-services/.cproject
new file mode 100644
index 0000000..3465f7a
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/.cproject
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/.gitignore b/user-crypto/miv-rv32-ccm-services/.gitignore
new file mode 100644
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/.project b/user-crypto/miv-rv32-ccm-services/.project
new file mode 100644
index 0000000..8e23413
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-ccm-services
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-ccm-services/README.md b/user-crypto/miv-rv32-ccm-services/README.md
new file mode 100644
index 0000000..c2a0798
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/README.md
@@ -0,0 +1,186 @@
+PolarFire User Crypto CCM Services example
+================================================================================
+This example project demonstrates the use of the following User Crypto Services
+for demonstrating CBC Counter Mode (CCM)
+
+ - CALSymEncAuthDMA()
+ - CALMAC()
+
+CCM is used to provide assurance of the confidentiality and the authenticity
+of computer data by combining the techniques of the Counter (CTR) mode and the
+Cipher Block Chaining-Message Authentication Code (CBC-MAC) algorithm.
+
+The example project demonstrates CCM functionality using the existing CTR-AES
+and CMAC-AES modes, which are supported by the TeraFire core and CAL software.
+The two supported TeraFire functions, namely CTR-AES and CMAC-AES can be used
+to construct CCM along with some additional minor application code, to perform
+the CCM padding requirements. The example project demonstrates how to pre-process
+the message data (e.g., any required padding), call the appropriate TeraFire
+C-API functions, and do any post-processing required to perform NIST standard
+compliant CCM.
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal followed by a menu system and instructions.
+
+This program displays the return data from User Crypto processor for digital
+signature generation and verification services.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Data Authenticated Encryption Using AES 128-bit key
+
+Select option '1' to perform authenticated encryption using Counter with CBC-MAC
+(CCM) algorithm. This example project reads the 128 bit key, 16 bytes of Nonce,
+64 bytes of plain text(P), and 16 bytes of additional authentication data (AAD)
+from UART terminal. The example project stores the keys in SNVM region using
+system controller SNVM service. After reading all the required data from UART
+terminal, the example project call **MACCcmEnrypt()** function to perform CCM
+encryption.
+
+The CCM algorithm compute the authentication field and encrypt the message data
+using Counter (CTR) mode. This CCM algorithm performs authenticated encryption
+with associated data for confidentiality and integrity. The plain text is both
+encrypted and used in computation of message authentication code according to
+the SATSYMTYPE_AES128 encryption algorithm and CCM mode. Both the encrypted data
+and tag are displayed on UART terminal.
+
+### Data Authenticated Decryption Using AES 128-bit key
+
+Select option '2' to perform authenticated decryption using Counter with CBC-MAC
+(CCM) algorithm. This example project reads the 128 bit key, 16 bytes of Nonce,
+64 bytes of cipher text(P), and 16 bytes of additional authentication data (AAD)
+from UART terminal. The example project stores the keys in SNVM region using
+system controller SNVM service. After reading all the required data from UART
+terminal, the example project call **MACCcmDecrypt()** function to perform CCM
+decryption. The CCM algorithm decrypt the encrypted message data using Counter
+(CTR) mode. The decrypted data contain the plain text message and the message
+authentication code and are displayed on UART terminal.
+
+**NOTE:**
+ You can calculate the MAC using CBC MAC function based on the decrypted plain
+ text message and compare the decrypted MAC and compute MAC value are equal
+ or not in order to authenticate the data.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+**NOTE:**
+ 1. If you try to enter data values other than 0 - 9, a - f, A - F, an error
+ message will be displayed on the serial terminal.
+ 2. You must enter all input data as whole bytes. If you enter the 128-bit
+ key {1230...0} as 0x12 0x3 and press return, this will be treated as
+ byte0 = 0x12, byte1 = 0x30, byte2-127 = 0x00.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality.You can use
+the RV32_CCM_msg_auth.ttl Tera Term Macro script present in project directory
+for testing Data Authenticated Encryption/Decryption Services.
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
diff --git a/user-crypto/miv-rv32-ccm-services/RV32_CCM_msg_auth.ttl b/user-crypto/miv-rv32-ccm-services/RV32_CCM_msg_auth.ttl
new file mode 100644
index 0000000..d8cef0b
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/RV32_CCM_msg_auth.ttl
@@ -0,0 +1,421 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+changedir '.'
+logopen "MAC_ccm_msg_auth.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto CCM service'
+
+setsync 1
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+;press any key
+send '5'
+pause 1
+
+; -------------------------------------------------------------------------------
+; Test Case 1
+; Inputs
+; 8, 3, 44, 20,
+; AES key
+; 40414243 44454647 48494A4B 4C4D4E4F
+; NONCE
+; 10111213 14151617 18191A1B
+; AAD
+; 00010203 04050607 08090A0B 0C0D0E0F 10111213
+; Message P
+; 20212223 24252627 28292A2B 2C2D2E2F 30313233 34353637
+
+; Output - Encrypted Data
+; E3B201A9 F5B71A7A 9B1CEAEC CD97E70B 6176AAD9 A4428AA5 484392FB C1B09951
+; -----------------------------------------------------------------------------
+send '1'
+pause 2
+
+;Key
+send '404142434445464748494a4b4c4d4e4f'
+pause 1
+
+;Nonce
+send '101112131415161718191a1b'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '000102030405060708090a0b0c0d0e0f10111213'
+pause 1
+send 13
+pause 1
+
+;MSG
+send '202122232425262728292A2B2C2D2E2F3031323334353637'
+pause 1
+send 13
+pause 1
+
+;M
+send '2'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+; -------------------------------------------------------------------------------
+; Test Case 2
+; Inputs
+; 8, 2, 32, 8
+; AES key
+; C0C1C2C3 C4C5C6C7 C8C9CACB CCCDCECF
+; NONCE
+; 00000004 030201A0 A1A2A3A4 A5
+; AAD
+; 00010203 04050607
+; Message P
+; 08090A0B 0C0D0E0F 10111213 14151617 18191A1B 1C1D1E1F
+
+; Output - Encrypted Data
+; 72C91A36 E135F8CF 291CA894 085C87E3 CC15C439 C9E43A3B A091D56E 10400916
+; -----------------------------------------------------------------------------
+
+send '1'
+pause 2
+
+;Key
+send 'C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF'
+pause 1
+
+;Nonce
+send '00000004030201A0A1A2A3A4A5'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '0001020304050607'
+pause 1
+send 13
+pause 1
+
+;MSG
+send '08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F'
+pause 1
+send 13
+pause 1
+
+;M
+send '2'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+; -------------------------------------------------------------------------------
+; Test Case 3
+; Inputs
+; 4, 8, 12, 8,
+; AES key
+; C0C1C2C3 C4C5C6C7 C8C9CACB CCCDCECF
+; NONCE
+; 10111213 141516
+; AAD
+; 00010203 04050607
+; Message P
+; 20212223
+
+; Output - Encrypted Data
+; 7162015B 4DAC255D
+; -----------------------------------------------------------------------------
+
+send '1'
+pause 2
+
+;Key
+send '404142434445464748494A4B4C4D4E4F'
+pause 1
+
+;Nonce
+send '10111213141516'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '0001020304050607'
+pause 1
+send 13
+pause 1
+
+;MSG
+send '20212223'
+pause 1
+send 13
+pause 1
+
+;M
+send '1'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+; -------------------------------------------------------------------------------
+; Test Case 4 Decryption
+; Inputs
+; 8, 3, 44, 20,
+; AES KEY
+; 40414243 44454647 48494A4B 4C4D4E4F
+; NONCE
+; 10111213 14151617 18191A1B
+; AAD
+; 00010203 04050607 08090A0B 0C0D0E0F 10111213
+; Encrypted Data
+; E3B201A9 F5B71A7A 9B1CEAEC CD97E70B 6176AAD9 A4428AA5 484392FB C1B09951
+
+; Output -
+; P
+; 20212223 24252627 28292A2B 2C2D2E2F 30313233 34353637
+; MAC
+; 67C99240 C7D51048
+; -----------------------------------------------------------------------------
+send '2'
+pause 2
+
+;Key
+send '404142434445464748494a4b4c4d4e4f'
+pause 1
+
+;Nonce
+send '101112131415161718191a1b'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '000102030405060708090a0b0c0d0e0f10111213'
+pause 1
+send 13
+pause 1
+
+;Encrypted data
+send 'E3B201A9F5B71A7A9B1CEAECCD97E70B6176AAD9A4428AA5484392FBC1B09951'
+pause 1
+send 13
+pause 1
+
+;M
+send '2'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+
+; -------------------------------------------------------------------------------
+; Test Case 5 Decryption
+; Inputs
+; 8, 2, 32, 8,
+; AES KEY
+; C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
+; NONCE
+; 00000004030201A0A1A2A3A4A5
+; AAD
+; 0001020304050607
+; Encrypted Data
+; 72C91A36E135F8CF291CA894085C87E3CC15C439C9E43A3BA091D56E10400916
+
+; Output -
+: P
+; 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+; MAC
+; F7B9056A 86926CF3
+; -----------------------------------------------------------------------------
+send '2'
+pause 2
+
+;Key
+send 'C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF'
+pause 1
+
+;Nonce
+send '00000004030201A0A1A2A3A4A5'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '0001020304050607'
+pause 1
+send 13
+pause 1
+
+;Encrypted data
+send '72C91A36E135F8CF291CA894085C87E3CC15C439C9E43A3BA091D56E10400916'
+pause 1
+send 13
+pause 1
+
+;M
+send '2'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+; -------------------------------------------------------------------------------
+; Test Case 6 Decryption
+; Inputs
+; 4, 8, 12, 8,
+; AES KEY
+; 40414243 44454647 48494A4B 4C4D4E4F
+; NONCE
+; 10111213 141516
+; AAD
+; 00010203 04050607
+; Encrypted Data
+; 7162015B 4DAC255D
+
+; Output
+; P
+; 20212223
+; MAC
+; 6084341B
+; -----------------------------------------------------------------------------
+send '2'
+pause 2
+
+;Key
+send '404142434445464748494A4B4C4D4E4F'
+pause 1
+
+;Nonce
+send '10111213141516'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '0001020304050607'
+pause 1
+send 13
+pause 1
+
+;Encrypted data
+send '7162015B4DAC255D'
+pause 1
+send 13
+pause 1
+
+;M
+send '1'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+; -------------------------------------------------------------------------------
+; Test Case 7
+; Inputs
+; [Tlen = 4]
+; Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+; Nonce = 9882578e750b9682c6ca7f8f86
+; Count = 0
+; Adata = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+; Payload = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+
+; Output
+; CT = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+; -----------------------------------------------------------------------------
+send '1'
+pause 2
+
+;Key
+send '43b1a6bc8d0d22d6d1ca95c18593cca5'
+pause 1
+
+;Nonce
+send '9882578e750b9682c6ca7f8f86'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f'
+pause 1
+
+;MSG
+send 'a2b381c7d1545c408fe29817a21dc435a154c87256346b05'
+pause 1
+send 13
+pause 1
+
+;M
+send '1'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+
+; -------------------------------------------------------------------------------
+; Test Case 8 Decryption
+; Inputs
+; [Tlen = 4]
+; Key = 43b1a6bc8d0d22d6d1ca95c18593cca5
+; Nonce = 9882578e750b9682c6ca7f8f86
+; Count = 0
+; Adata = 2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f
+; CT = cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677
+
+; Output
+; Payload = a2b381c7d1545c408fe29817a21dc435a154c87256346b05
+; MAC = 95DA703C
+; -----------------------------------------------------------------------------
+send '2'
+pause 2
+
+;Key
+send '43b1a6bc8d0d22d6d1ca95c18593cca5'
+pause 1
+
+;Nonce
+send '9882578e750b9682c6ca7f8f86'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f'
+pause 1
+
+;Encrypted data
+send 'cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677'
+pause 1
+send 13
+pause 1
+
+;M
+send '1'
+pause 5
+
+;Send dummy
+send '5'
+pause 2
+
+pause 5
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw Debug.launch b/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw Debug.launch
new file mode 100644
index 0000000..1175fc7
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw attach.launch b/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw attach.launch
new file mode 100644
index 0000000..460e8d3
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/miv-rv32-ccm-services hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/ccm.c b/user-crypto/miv-rv32-ccm-services/src/application/ccm.c
new file mode 100644
index 0000000..be3d28b
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/ccm.c
@@ -0,0 +1,456 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file ccm.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief PolarFire User crypto MAC-CCM algorithm implementation. See file "ccm.h"
+ * for description of the functions implemented in this file.
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include "hal/hal.h"
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+#include "ccm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+__attribute__ ((section (".crypto_data")))static uint8_t g_mac[100];
+__attribute__ ((section (".crypto_data"))) uint8_t A[100] = {0x00}; /* A_i blocks for encryption input */
+__attribute__ ((section (".crypto_data"))) static uint8_t S[100]; /* S_i = encrypted A_i blocks */
+static uint8_t __attribute__ ((section (".crypto_data")))B[100] = {0x00};/* B_i blocks for CBC-MAC input */
+
+extern SATR CCMMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+/*==============================================================================
+ Clear CCM global variable.
+ */
+void clear_ccm_var(void)
+{
+ uint16_t var = 0;
+
+ for(var = 0; var < 100; var++)
+ {
+ g_mac[var] = 0;
+ A[var] = 0;
+ S[var] = 0;
+ B[var] = 0;
+ }
+}
+
+static inline int int_to_uint16(uint8_t *field, uint16_t value)
+{
+ field[0] = (value >> 8) & 0xff;
+ field[1] = value & 0xff;
+ return 2;
+}
+
+static inline int int_to_uint32(uint8_t *field, uint32_t value)
+{
+ field[0] = (value >> 24) & 0xff;
+ field[1] = (value >> 16) & 0xff;
+ field[2] = (value >> 8) & 0xff;
+ field[3] = value & 0xff;
+ return 4;
+}
+
+static inline int int_to_uint64(unsigned char *field, uint64_t value)
+{
+ field[0] = (value >> 56) & 0xff;
+ field[1] = (value >> 48) & 0xff;
+ field[2] = (value >> 40) & 0xff;
+ field[3] = (value >> 32) & 0xff;
+ field[4] = (value >> 24) & 0xff;
+ field[5] = (value >> 16) & 0xff;
+ field[6] = (value >> 8) & 0xff;
+ field[7] = value & 0xff;
+ return 8;
+}
+static void set_counter(uint8_t A[CCM_BLOCKSIZE],uint16_t L,uint16_t cnt,uint16_t C)
+{
+ uint8_t i_;
+ volatile uint16_t temp = 0;
+ memset((A) + CCM_BLOCKSIZE - (L), 0, (L));
+
+ temp = (((uint16_t)1 << (8 * L)) - 1);
+
+ (C) = (cnt) & 0xFFFFFFFF;
+
+ for (i_ = CCM_BLOCKSIZE - 1; (C) && (i_ > (L)); --i_, (C) >>= 8)
+ {
+ (A)[i_] |= (C) & 0xFF;
+ }
+}
+
+static uint8_t roundUp(uint8_t numToRound, uint8_t multiple)
+{
+ return ((numToRound + multiple - 1) / multiple) * multiple;
+}
+
+static inline void
+block0(size_t M, /* number of auth bytes */
+ size_t L, /* number of bytes to encode message length */
+ size_t la, /* l(a) octets additional authenticated data */
+ size_t lm, /* l(m) message length */
+ uint8_t nonce[CCM_BLOCKSIZE],
+ uint8_t *result)
+{
+ uint8_t i;
+
+ result[0] = CCM_FLAGS(la, M, L);
+
+ /* copy the nonce */
+ memcpy(result + 1, nonce, CCM_BLOCKSIZE - L - 1);
+
+ for (i = 0; i < L; i++)
+ {
+ result[15-i] = lm & 0xff;
+ lm >>= 8;
+ }
+}
+
+/*==============================================================================
+ Form input block B1.. Bn for Authentication.
+ */
+static uint8_t
+add_auth_data(const uint8_t *msg, size_t la, uint8_t *B1)
+{
+ size_t i,j;
+ uint8_t status = 0u;
+ uint8_t len = 0;
+
+ memset(B1, 0, CCM_BLOCKSIZE);
+
+ if (!la)
+ {
+ return 0;
+ }
+
+ if (la < 0xFF00)
+ {
+ j = 2;
+ int_to_uint16(B1, la);
+ }
+ else if (la <= UINT32_MAX)
+ {
+ j = 6;
+ int_to_uint16(B1, 0xFFFE);
+ int_to_uint32(B1+2, la);
+ }
+ else
+ {
+ j = 10;
+ int_to_uint16(B1, 0xFFFF);
+ int_to_uint64(B1+2, la);
+ }
+
+ i = min(CCM_BLOCKSIZE - j, la);
+ memcpy(B1 + j, msg, i);
+ la -= i;
+ msg += i;
+ len = i+j;
+ B1 += len;
+
+ while (la > CCM_BLOCKSIZE)
+ {
+ for (i = 0; i < CCM_BLOCKSIZE; ++i)
+ {
+ *B1++ = *msg++;
+ }
+ la -= CCM_BLOCKSIZE;
+ len += CCM_BLOCKSIZE;
+ }
+
+ if (la)
+ {
+ memcpy(B1, msg, la);
+ len += CCM_BLOCKSIZE;
+ }
+
+ return len;
+}
+
+/*==============================================================================
+ Encryption using AES-128
+ */
+static inline void
+ccm_aes_encrypt(size_t L, uint16_t counter,
+ uint8_t *msg, size_t len,
+ uint8_t A[CCM_BLOCKSIZE],
+ uint8_t S[CCM_BLOCKSIZE],
+ uint8_t* key,
+ uint8_t *pDest)
+{
+ static uint16_t counter_tmp;
+ uint8_t status = 0u;
+
+ set_counter(A, L, counter, counter_tmp);
+
+ status = CALSymEncryptDMA(SATSYMTYPE_AES128, (uint32_t *)key,
+ SATSYMMODE_CTR, A, SAT_TRUE, msg,
+ pDest, 16, X52CCR_DEFAULT);
+
+ CALPKTrfRes(SAT_TRUE);
+
+}
+
+/*==============================================================================
+ Input Block B calculation for MAC
+ */
+uint16_t
+ccm_mac_block(size_t M, size_t L, uint8_t *nonce,
+ uint8_t *msg, size_t lm,
+ const uint8_t *aad, size_t la)
+{
+ volatile uint8_t *b_ptr = (uint8_t *)&B;
+ uint8_t return_len = 0;
+ uint8_t len = 0;
+ uint8_t i = 0;
+
+ /*
+ * Clear B array.
+ */
+ for(i = 0; i < sizeof(B); i++)
+ {
+ B[i] = 0;
+ }
+
+ /* Create the initial authentication block B0 i.e. define a sequence of
+ * blocks B0
+ */
+ block0(M, L, la, lm, nonce, B);
+ b_ptr += CCM_BLOCKSIZE;
+ return_len = CCM_BLOCKSIZE;
+
+ /* Input Block B1 ... Bn */
+ len = add_auth_data( aad, la, (uint8_t *)b_ptr);
+ len = roundUp(len, 16);
+ b_ptr += len;
+ return_len += len;
+
+ /* Last Block calculation. */
+ memcpy((uint8_t *)b_ptr, msg, lm);
+ len = roundUp(lm, 16);
+ return_len += len;
+
+ return return_len;
+}
+
+/*==============================================================================
+ Form Input block and perform CCM Encryption
+ */
+uint16_t
+ccm_encrypt_message(size_t M, size_t L, uint8_t nonce[CCM_BLOCKSIZE],
+ uint8_t *msg, size_t lm, uint8_t *key, uint8_t *pDest)
+{
+ uint8_t status = 0u;
+ uint16_t msg_len = 0;
+ size_t i,j;
+ size_t len;
+ uint16_t counter_tmp;
+ uint16_t counter = 1;
+
+ /* Save original length */
+ len = lm;
+
+ /* Initialize block template */
+ A[0] = L-1;
+
+ /* Copy the nonce */
+ memcpy(A + 1, nonce, CCM_BLOCKSIZE - L - 1);
+
+ while (lm >= CCM_BLOCKSIZE)
+ {
+ /* Encrypt */
+ ccm_aes_encrypt( L, counter, msg, CCM_BLOCKSIZE, A, S, key, pDest);
+
+ /* Update local pointers */
+ lm -= CCM_BLOCKSIZE;
+ msg += CCM_BLOCKSIZE;
+ pDest += CCM_BLOCKSIZE;
+ counter++;
+ msg_len += CCM_BLOCKSIZE;
+ }
+
+ if (lm)
+ {
+ /* Encrypt */
+ ccm_aes_encrypt( L, counter, msg, lm, A, S, key, pDest);
+
+ /* Update local pointers */
+ msg += lm;
+ msg_len += lm;
+ pDest += lm;
+ }
+
+ /* Calculate S_0 */
+ set_counter(A, L, 0, counter_tmp);
+
+ status = CALSymEncryptDMA(SATSYMTYPE_AES128, (uint32_t *)key,
+ SATSYMMODE_CTR, A, SAT_TRUE, msg,
+ S , 16, X52CCR_DEFAULT);
+
+ CALPKTrfRes(SAT_TRUE);
+
+ return msg_len;
+}
+
+/*==============================================================================
+ CCM Decryption
+ */
+uint16_t
+ccm_decrypt_message(size_t M, size_t L,
+ uint8_t nonce[CCM_BLOCKSIZE],
+ uint8_t *msg, size_t lm,
+ uint8_t *key,
+ uint8_t *pDest)
+{
+ uint16_t counter_tmp = 0;
+ uint16_t counter = 1;
+ uint16_t i = 0;
+ uint16_t error, n = 0;
+ uint8_t status = 0;
+
+ for(i = 0; i < 80; i++)
+ {
+ A[i] = 0;
+ }
+
+ if (lm < M)
+ goto error;
+
+ /* save original length */
+ lm -= M;
+
+ /* Initialize block template */
+ A[0] = L-1;
+
+ /* Copy the nonce */
+ memcpy(A + 1, nonce, CCM_BLOCKSIZE - L - 1);
+
+ while (lm >= CCM_BLOCKSIZE)
+ {
+ /* Decrypt */
+ ccm_aes_encrypt( L, counter, msg, CCM_BLOCKSIZE, A, S, key, pDest);
+
+ for(i = 0; i < CCM_BLOCKSIZE; i++)
+ {
+ S[i] = pDest[i];
+ }
+
+ /* Update local pointers */
+ lm -= CCM_BLOCKSIZE;
+ msg += CCM_BLOCKSIZE;
+ pDest += CCM_BLOCKSIZE;
+ counter++;
+ }
+
+ if (lm)
+ {
+ /* Decrypt */
+ ccm_aes_encrypt( L, counter, msg, lm, A, S, key, pDest);
+
+ /* update local pointers */
+ msg += lm;
+ pDest += lm;
+
+ }
+
+ /* Calculate S_0 */
+ set_counter(A, L, 0, counter_tmp);
+ CALSymEncryptDMA(SATSYMTYPE_AES128, (uint32_t *)key,
+ SATSYMMODE_CTR, A, SAT_TRUE, msg,
+ S , 16, X52CCR_DEFAULT);
+
+ CALPKTrfRes(SAT_TRUE);
+
+ return 0;
+
+ error:
+ return -1;
+}
+
+/*==============================================================================
+ CCM Encryption
+ */
+void
+MACCcmEnrypt(size_t M, size_t L, uint8_t *pNonce, uint8_t *pSrc, size_t lm,
+ const uint8_t *pAad, size_t la, uint16_t *pKey, void *pDest)
+{
+ uint8_t i = 0;
+ uint32_t len = 0;
+ uint8_t *p_msg = pDest;
+ uint8_t status = 0;
+
+ /* Initializes the Athena Processor. */
+ CALIni();
+
+ /* Calculate MAC input block. */
+ len = ccm_mac_block(M, L, pNonce, pSrc, lm, pAad, la);
+
+ /* Calculate MAC. */
+ status = CCMMAC(SATMACTYPE_AESCMAC128, (uint32_t *)pKey, 16, B, len, g_mac);
+
+ /* Encrypt the message. */
+ len = ccm_encrypt_message(M, L, pNonce, pSrc, lm, (uint8_t *)pKey, pDest);
+ p_msg += len;
+
+ /* The authentication value U is computed by encrypting T with the key
+ * stream block S_0 and truncating it to the desired length.
+ * U := T XOR first-M-bytes( S_0 )
+ */
+ for (i = 0; i < M; ++i)
+ {
+ *p_msg++ = S[i] ^ g_mac[i];
+ }
+}
+
+/*==============================================================================
+ Perform CCM decryption and calculate MAC value of decrypted data for
+ verification.
+ */
+void
+MACCcmDecrypt(size_t M, size_t L, uint8_t *pNonce, uint8_t *pEncMsg, size_t lm,
+ const uint8_t *pAad, size_t la, uint16_t *pKey, uint8_t *pDest,
+ uint8_t *pMAC)
+{
+ uint8_t status = 0;
+ uint8_t i = 0;
+
+ /* Initializes the Athena Processor. */
+ CALIni();
+
+ /* Decrypt the encrypted message.*/
+ ccm_decrypt_message(M, L, pNonce, pEncMsg, lm, (uint8_t *)pKey, pDest);
+
+ for(i = 0; i < M; i++)
+ {
+ pMAC[i] = S[i];
+ }
+
+}
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/ccm.h b/user-crypto/miv-rv32-ccm-services/src/application/ccm.h
new file mode 100644
index 0000000..d528701
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/ccm.h
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file ccm.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This file contains the application programming interface for the
+ * PolarFire User Crypto MAC using CCM service.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage PolarFire User Crypto CCM Bare Metal Driver.
+ *//*=========================================================================*/
+/*=========================================================================*//**
+ @mainpage CCM MAC Algorithm implementation.
+ CCM(Counter with CBC-MAC) is used to provide assurance of the confidentiality
+ and the authenticity of computer data by combining the techniques of the
+ Counter (CTR) mode and the Cipher Block Chaining-Message Authentication Code
+ (CBC-MAC) algorithm. The TeraFire functions, namely CTR-AES is used to
+ construct CCM along with some additional minor application code, to perform
+ the CCM padding requirements.
+
+ Initialization and Configuration
+ The CAL library driver is initialized through a call to the CALIni()
+ function. The CALIni() function must be called before any other
+ CAL Library driver or CCM functions is called.
+
+ CCM services.
+ The CCM driver can ebe used to execute Authentication encryption and
+ decryption services using the following function.
+ • MACCcmEnrypt ()
+ • MACCcmDecrypt ()
+
+ *//*=========================================================================*/
+
+#ifndef __CCM_H
+#define __CCM_H 1
+
+#include "hal/hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * Macro definitation.
+ */
+#define CCM_BLOCKSIZE 16
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define CCM_FLAGS(A,M,L) (((A > 0) << 6) | (((M - 2)/2) << 3) | (L - 1))
+#define MASK_L(_L) ((1 << 8 * _L) - 1)
+
+ /***************************************************************************//**
+ * Global Structure.
+ */
+struct test_vector {
+ size_t M, L; /* M - Number of Authenticate bytes.
+ L - Number of bytes to encode message length. */
+ size_t lm; /* overall message length*/
+ size_t la; /* number of bytes additional data */
+ uint8_t key[CCM_BLOCKSIZE];
+ uint8_t nonce[CCM_BLOCKSIZE];
+ uint8_t msg[128];
+ uint8_t aad[128];
+ uint8_t output[128];
+ uint8_t dec_mac[128];
+};
+
+ /***************************************************************************//**
+ * Global Functions.
+ */
+ /***************************************************************************//**
+ * The function MACCcmEnrypt() performs authenticated encryption with associated
+ * data, for confidentiality and integrity. The associated data, pointed at by
+ * pAad, with byte length la, is used in the computation of the message
+ * authentication code and but not encrypted and is not included in the output
+ * of CCM mode. AAD can be used to authenticate plaintext packet headers, or
+ * contextual information that affects the interpretation of the message. Users
+ * who do not wish to authenticate additional data can provide a string of
+ * length zero. The data pointed at by pSrc, is encrypted and used in the
+ * computation of the message authentication code according to the
+ * SATSYMTYPE_AES128 encryption algorithm, and SATSYMMODE_CTR mode. The length of
+ * the data pointed by pSrc is specified by lm. The final result consists of the
+ * encrypted message followed by the encrypted authentication value. And will be
+ * stored at the location pointed at by pDest. The byte length of the message
+ * authentication code is specified by M. The data will be encrypted using the
+ * key pointed at by pKey. The Nonce is pointed at by pNonce.
+
+ * @param M The M parameter specifies the the size of authentication
+ * field.
+ *
+ * @param L The L parameter specifies the number of octets in length
+ * field.
+ *
+ * @param pNonce The pNonce parameter is a pointer to the buffer where the
+ * nonce value will be stored.
+ *
+ * @param pSrc The pSrc parameter is pointer to the plaintext/authenticate
+ * data buffer.
+ *
+ * @param lm The lm parameter specifies the length of the plaintext in
+ * bytes the encrypt/authenticate.
+ *
+ * @param pAad The aad parameter is pointer the Additional authenticated
+ * data buffer.
+ *
+ * @param la The la parameter specifies the length of Additional
+ * authenticated data buffer.
+ *
+ * @param pKey The pKey parameter is pointer to key.
+ *
+ * @param pDest The pDest parameter is a pointer to ciphertext data
+ * buffer.
+ *
+ * @return This function does not return any value.
+ *
+ * Example:
+ * @code
+ * /* CCM Encryption *//*
+ * MACCcmEnrypt(data.M,
+ * data.L,
+ * data.nonce,
+ * data.msg,
+ * data.lm,
+ * data.aad,
+ * data.la,
+ * data.key,
+ * data.output);
+ * @endcode
+ */
+void
+MACCcmEnrypt(size_t M, size_t L, uint8_t *pNonce, uint8_t *pSrc, size_t lm,
+ const uint8_t *pAad, size_t la, uint16_t *pKey, void *pDest);
+
+/***************************************************************************//**
+ * The MACCcmDecrypt() function performs authenticated decryption with
+ * additional authenticated data, for confidentiality and integrity. The
+ * additional authenticated data data, pointed at by pAad, with byte length la,
+ * is used in the computation of the message authentication code, but is not
+ * decrypted. The data pointed at by pEncMsg, with byte length lm, is both
+ * decrypted and used in the computation of the message authentication code
+ * according to the selected decryption algorithm, based on SATSYMTYPE_AES128
+ * encryption algorithm, and SATSYMMODE_CTR mode.
+ * The decrypted data will be stored at the location pointed at by pDest, and
+ * the message authentication code will be compared to the value stored at the
+ * location pointed at by pMAC; The byte length of the message authentication
+ * code is specified by la. The data will be decrypted using the key pointed at
+ * by pKey variable. The Nonce value is pointed at by pNonce.
+
+ * @param M The M parameter specifies the length of the message
+ * authentication code in bytes.
+ *
+ * @param L The L parameter specifies the number of octets in length
+ * field.
+ *
+ * @param pNonce The pNonce parameter is a pointer to the buffer where the
+ * nonce value will be stored.
+ *
+ * @param pEncMsg The pEncMsg parameter is pointer to the ciphertext/verify
+ * data buffer.
+ *
+ * @param lm The lm parameter specifies the length of the plaintext in
+ * bytes the encrypt/authenticate.
+ *
+ * @param pAad The pAad parameter is pointer the Additional
+ * authenticated data buffer.i.e. verify-only data buffer.
+ *
+ * @param la The la parameter specifies the length of Additional
+ * authenticated data buffer.i.e. verify-only data buffer.
+ *
+ * @param pKey The pKey parameter is pointer to key.
+ *
+ * @param pDest The pDest parameter is a pointer to plaintext data
+ * buffer.
+ *
+ * @param pMAC The pMAC parameter is a pointer to the message
+ * authentication code.
+ *
+ *
+ * @return This function does not return any value.
+ *
+ * Example:
+ * @code
+ * @endcode
+ */
+void
+MACCcmDecrypt(size_t M, size_t L, uint8_t *pNonce, uint8_t *pEncMsg, size_t lm,
+ const uint8_t *pAad, size_t la, uint16_t *pKey, uint8_t *pDest,
+ uint8_t *pMAC);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CCM_H */
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/ccm_mac.c b/user-crypto/miv-rv32-ccm-services/src/application/ccm_mac.c
new file mode 100644
index 0000000..145c513
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/ccm_mac.c
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file ccm_mac.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief PolarFire user crypto MAC-CCM algorithm- MAC implementation.
+ *
+ */
+#include "cal/calpolicy.h"
+#include "cal/caltypes.h"
+#include "cal/calenum.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/calcontext.h"
+#include "cal/shaf5200.h"
+#include "cal/sym.h"
+#include "cal/aesf5200.h"
+
+static __attribute__ ((section (".crypto_data")))SATMACTYPE CurMAC=SATMACTYPE_NULL;
+static __attribute__ ((section (".crypto_data")))SATSYMTYPE CurSym=SATSYMTYPE_NULL;
+static __attribute__ ((section (".crypto_data")))SATUINT32_t uiIV[4];
+static __attribute__ ((section (".crypto_data")))SATUINT32_t uiCMACK[4];
+static __attribute__ ((section (".crypto_data")))SATUINT32_t uiSymMsgLen;
+
+static SATR AES_MAC_Write(const void *pBuffer, SATUINT32_t uiBufLen)
+{
+ SATR rReturn;
+
+ SATUINT32_t uiBytesCBC,i;
+ SATUINT8_t *pui8Buffer, *pui8IV, *pui8K;
+ pui8Buffer=(SATUINT8_t *)pBuffer;
+
+ /* Validate length */
+ if(uiBufLen > uiSymMsgLen)
+ {
+ return SATR_BADLEN;
+ }
+
+ /* Calculate number of CBC bytes to process before final block */
+ if((uiSymMsgLen - uiBufLen) > 0)
+ {
+ uiBytesCBC = uiBufLen;
+ }
+ else
+ {
+ if(uiBufLen > 16)
+ {
+ if((uiBufLen % 16) != 0)
+ {
+ uiBytesCBC = uiBufLen - (uiBufLen % 16);
+ }
+ else
+ {
+ uiBytesCBC = uiBufLen - 16;
+ }
+ }
+ else
+ {
+ uiBytesCBC = 0;
+ }
+ }
+
+ /* Update message length state */
+ uiSymMsgLen -= uiBufLen;
+
+ /* Process all message blocks except last */
+ if (uiBytesCBC >= 16)
+ {
+ aesf5200aes (CurSym, SATSYMMODE_CBC, uiIV, SAT_TRUE, pui8Buffer,
+ SAT_NULL, uiBytesCBC, SAT_FALSE);
+
+ rReturn = CALSymTrfRes(SAT_TRUE);
+
+ pui8Buffer += uiBytesCBC;
+ }
+
+ /* XOR final message with subkey */
+ if(uiSymMsgLen == 0)
+ {
+ /* Calculate size of final block */
+ pui8IV = (SATUINT8_t*)uiIV;
+ pui8K = (SATUINT8_t*)uiCMACK;
+ for (i = 0; i < (uiBufLen - uiBytesCBC); i++)
+ {
+ *pui8IV = *pui8IV ^ *pui8Buffer;
+ pui8IV++;
+ pui8Buffer++;
+ }
+ if (i<16)
+ {
+ *pui8IV = *pui8IV ^ 0x80;
+ pui8IV++;
+ i++;
+ }
+ for (; i < 16; i++)
+ {
+ pui8IV++;
+ }
+
+ /* Encrypt final block */
+ rReturn = aesf5200aes(CurSym, SATSYMMODE_ECB, SAT_NULL, SAT_FALSE,
+ uiIV, uiIV, 16, SAT_FALSE);
+ if(rReturn != SATR_SUCCESS)
+ {
+ return rReturn;
+ }
+
+ rReturn = CALSymTrfRes(SAT_TRUE);
+ if(rReturn != SATR_SUCCESS)
+ {
+ return rReturn;
+ }
+ }
+
+ return rReturn;
+}
+
+SATR MACWrite(const void *pBuffer, SATUINT32_t uiBufLen)
+{
+ SATR rRet;
+
+ if(CurMAC == SATMACTYPE_NULL)
+ {
+ return SATR_BADMACTYPE;
+ }
+
+ if(pBuffer == SAT_NULL)
+ {
+ return SATR_BADPARAM;
+ }
+
+ if(CurMAC >= SATMACTYPE_AESCMAC128 && CurMAC <= SATMACTYPE_AESCMAC256)
+ {
+ rRet = AES_MAC_Write(pBuffer, uiBufLen);
+ }
+ /* No default else statement - CALMACIni checks type and sets it to SAT_NULL
+ if it's invalid. Then this function checks & returns if type ==SAT_NULL */
+ return rRet;
+}
+
+static void macsubkey(const void *pSubKeyIn, void *pSubKeyOut)
+{
+ SATUINT8_t uiC,uiCNew;
+ SATUINT8_t *pui8In,*pui8Out;
+ SATINT8_t i;
+ uiC = 0;
+
+ pui8In = ((SATUINT8_t *)pSubKeyIn) + 15;
+ pui8Out = ((SATUINT8_t *)pSubKeyOut) + 15;
+ for( i = 15; i >= 0; i--)
+ {
+ uiCNew = (*pui8In & 0x80) >> 7;
+ *pui8Out = *pui8In << 1 | uiC;
+ pui8Out--;
+ pui8In--;
+ uiC = uiCNew;
+ }
+ pui8In = ((SATUINT8_t *)pSubKeyIn) + 15;
+ pui8Out = ((SATUINT8_t *)pSubKeyOut) + 15;
+ if (uiC)
+ {
+ *pui8Out = *pui8In ^ 0x87;
+ }
+}
+
+SATR MACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ SATUINT32_t uiMsgLen)
+{
+ SATUINT32_t i;
+ SATR rReturn = SATR_BADMACTYPE;
+
+ if (pKey == SAT_NULL)
+ {
+ return SATR_BADPARAM;
+ }
+
+ for( i = 0; i < 4; i++)
+ {
+ uiIV[i] = 0;
+ }
+
+ CurMAC = eMACType;
+ uiSymMsgLen = uiMsgLen;
+ CurSym = SATSYMTYPE_AES128;
+ CALSymEncrypt(CurSym, pKey, SATSYMMODE_ECB, SAT_NULL, SAT_FALSE, uiIV, uiCMACK, 128/8);
+
+ CALSymTrfRes(SAT_TRUE);
+ macsubkey(uiCMACK,uiCMACK);
+
+ if ((uiMsgLen & 0xf) || (uiMsgLen == 0))
+ {
+ macsubkey(uiCMACK,uiCMACK);
+ }
+
+ return SATR_SUCCESS;
+}
+
+SATR MACRead(void *pMAC)
+{
+ SATR rReturn = SATR_SUCCESS;
+
+ if(CurMAC == SATMACTYPE_NULL)
+ {
+ return SATR_BADMACTYPE;
+ }
+ else if(CurMAC >= SATMACTYPE_AESCMAC128 && CurMAC <= SATMACTYPE_AESCMAC256)
+ {
+ CALMemCopy(pMAC, uiIV, 16 );
+ CALMemClear(uiIV, 16);
+ rReturn = SATR_SUCCESS;
+ }
+ else
+ {
+ return SATR_BADMACTYPE;
+ }
+
+ /* Clear eCurMAC as data has been read */
+ CurMAC = SATMACTYPE_NULL;
+ return rReturn;
+}
+
+SATR CCMMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC)
+{
+ SATR rReturn;
+
+ /* Initialize MAC operation */
+ rReturn = MACIni(eMACType, pKey, uiKeyLen, uiMsgLen);
+ if (rReturn != SATR_SUCCESS)
+ {
+ return rReturn;
+ }
+
+ /* Write message */
+ rReturn = MACWrite(pMsg, uiMsgLen);
+ if (rReturn != SATR_SUCCESS)
+ {
+ return rReturn;
+ }
+
+ /* Read resulting MAC */
+ rReturn = MACRead(pMAC);
+ return rReturn;
+}
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/helper.c b/user-crypto/miv-rv32-ccm-services/src/application/helper.c
new file mode 100644
index 0000000..914f872
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/helper.c
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include
+#include
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+)
+{
+ uint32_t inc;
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count % 2) == 0)
+ {
+ ret_size = count / 2;
+ }
+ else
+ {
+ if(size != 1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count / 2) + 1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/helper.h b/user-crypto/miv-rv32-ccm-services/src/application/helper.h
new file mode 100644
index 0000000..242514d
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/helper.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+#define DATA_LENGTH_32_BYTES 32
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+extern UART_instance_t g_uart;
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-ccm-services/src/application/main.c b/user-crypto/miv-rv32-ccm-services/src/application/main.c
new file mode 100644
index 0000000..7938803
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/application/main.c
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Application demonstrating the CCM cryptography service. Please see the
+ * Readme.md for more details.
+ *
+ */
+#include "cal/calini.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#include "helper.h"
+#include "ccm.h"
+
+/******************************************************************************
+ * User Crypto base address. This will be used in config_user.h in CAL.
+ *****************************************************************************/
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+************* PolarFire User Crypto CCM Example Project **********************\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the PolarFire User Crypto \r\n\
+ CCM service using AES cipher Services. The following CCM services \r\n\
+ are demonstrated:\r\n\
+ 1 - Encryption and authenticated.\r\n\
+ 2 - Decryption and authenticated.\r\n";
+
+const uint8_t g_select_operation_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select the CCM operation to perform:\r\n\
+ Press key '1' to perform Encryption and Authenticated \r\n\
+ Press key '2' to perform Decryption and Authenticated \r\n\
+------------------------------------------------------------------------------\r\n";
+
+static const uint8_t aes_encrypt_select_msg[] =
+"\r\n Selected Encryption and Authenticated using CCM. \r\n";
+
+static const uint8_t aes_decrypt_select_msg[] =
+"\r\n Selected Decryption and Authenticated using CCM. \r\n";
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+static const uint8_t read_key_msg[] =
+"\r\n Enter the 128-bit/16-byte key: \r\n";
+
+static const uint8_t read_nonce[] =
+"\r\n Enter the Nonce (max : 16 Bytes): \r\n";
+
+static const uint8_t read_aad[] =
+"\r\n Enter the Additional authenticated data (max : 32 Bytes): \r\n";
+
+static const uint8_t read_msg[] =
+"\r\n Enter the input data to encrypt and authenticate (max : 64 bytes):\r\n";
+
+static const uint8_t read_MAC_len[] =
+"\r\n Enter the Number of octets in authentication field: \r\n\
+ Press key '1' for 4 bytes \r\n\
+ Press key '2' for 8 bytes \r\n\
+ Press key '3' for 12 bytes \r\n\
+ Press key '4' for 16 bytes \r\n";
+
+static const uint8_t read_dec_msg[] =
+"\r\n Enter the encrypted and authenticated message (max : 64 bytes):\r\n";
+
+volatile __attribute__ ((section (".crypto_data"))) struct test_vector data = { 0x00 };
+
+static void clear_ccm_var(void)
+{
+ uint16_t var = 0;
+
+ data.M = 0;
+ data.L = 0;
+ data.lm = 0;
+ data.la = 0;
+
+ for(var = 0; var < CCM_BLOCKSIZE; var++)
+ {
+ data.key[var] = 0;
+ data.nonce[var] = 0;
+ }
+
+ for(var = 0; var < 100; var++)
+ {
+ data.msg[var] = 0;
+ data.output[var] = 0;
+ data.dec_mac[var] = 0;
+ }
+}
+
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Display the choice of cryptographic operation to perform.
+ */
+static void display_operation_choices(void)
+{
+ UART_send(&g_uart, g_select_operation_msg, sizeof(g_select_operation_msg));
+}
+
+/*==============================================================================
+ Display the Option to continue.
+ */
+static void display_option(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_buff[1];
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Press any key to continue.\r\n",
+ sizeof("\r\n Press any key to continue.\r\n"));
+ do
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ } while(0u == rx_size);
+}
+
+/*==============================================================================
+ Perform CCM encryption.
+ */
+void perform_ccm_encrypt( void )
+{
+ uint16_t len = 0;
+ uint8_t addr = 0x4;
+ uint8_t i = 0x4;
+ uint8_t status = 0;
+ uint8_t text[256] = {0x00};
+ uint8_t admin[4] = {0x00};
+ uint8_t input_text[256] = {0x00};
+ uint8_t user_key[12] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x10, 0x11};
+
+
+ /* Clear input and output variables */
+ clear_ccm_var();
+
+ /* Get key. */
+ get_input_data((uint8_t*)&data.key, 16u, read_key_msg, sizeof(read_key_msg));
+
+ /* Nonce N */
+ len = get_input_data((uint8_t*)&data.nonce, 16u, read_nonce, sizeof(read_nonce));
+ data.L = 15 - len;
+
+ /* Additional authenticated data a */
+ data.la = get_input_data((uint8_t*)&data.aad, 32u, read_aad, sizeof(read_aad));
+
+ /* Message m */
+ data.lm = get_input_data((uint8_t*)data.msg, 64u, read_msg, sizeof(read_msg));
+
+ /* Read MAC length */
+ get_input_data((uint8_t*)&data.M, 1u, read_MAC_len, sizeof(read_MAC_len));
+ data.M *= 4;
+
+ /* CCM Encryption */
+ MACCcmEnrypt(data.M,
+ data.L,
+ (uint8_t*)data.nonce,
+ (uint8_t*)data.msg,
+ data.lm,
+ (uint8_t*)data.aad,
+ data.la,
+ (uint16_t*)data.key,
+ (uint8_t *)data.output);
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Encrypted and Authentication data:\r\n",
+ sizeof("\r\n Encrypted and Authentication data:\r\n"));
+ display_output((uint8_t* )data.output, data.lm + data.M);
+}
+
+/*==============================================================================
+ Perform CCM decryption.
+ */
+void perform_ccm_decrypt( void )
+{
+ uint16_t len = 0;
+ uint8_t addr = 0x4;
+ uint8_t i = 0x4;
+ uint8_t status = 0;
+ uint8_t text[256] = {0x00};
+ uint8_t admin[4] = {0x00};
+ uint8_t input_text[256] = {0x00};
+ uint8_t user_key[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, \
+ 0x09, 0x0a, 0xb, 0x0c};
+
+ /* Clear input and output variables */
+ clear_ccm_var();
+
+ /* Get key. */
+ get_input_data((uint8_t*)&data.key, 16u, read_key_msg, sizeof(read_key_msg));
+
+ /* Nonce N */
+ len = get_input_data((uint8_t*)&data.nonce, 16u, read_nonce,
+ sizeof(read_nonce));
+
+ data.L = 15 - len;
+
+ /* Additional authenticated data a */
+ data.la = get_input_data((uint8_t*)&data.aad, 32u, read_aad,
+ sizeof(read_aad));
+
+ /* Encrypted and authenticated message c */
+ data.lm = get_input_data((uint8_t*)data.msg, 64u, read_dec_msg,
+ sizeof(read_dec_msg));
+
+ /* Read MAC length */
+ get_input_data((uint8_t*)&data.M, 1u, read_MAC_len, sizeof(read_MAC_len));
+ data.M *= 4;
+
+ /* Decrypt and Authenticate the input data.*/
+ MACCcmDecrypt( data.M,
+ data.L,
+ (uint8_t*)data.nonce,
+ (uint8_t*)data.msg,
+ data.lm,
+ (uint8_t*)data.aad,
+ data.la,
+ (uint16_t*)&data.key,
+ (uint8_t *)&data.output,
+ (uint8_t *)&data.dec_mac);
+
+ /* Display decrypted data and MAC value. */
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Decrypted data:\r\n",
+ sizeof("\r\n Decrypted data:\r\n"));
+ display_output((uint8_t*)(data.output), data.lm - data.M);
+
+ UART_send(&g_uart, (const uint8_t *)"\r\n Authenticated data (MAC):\r\n",
+ sizeof("\r\n Authenticated data (MAC):\r\n"));
+ display_output((uint8_t*)(data.dec_mac), data.M);
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+int main( void )
+{
+ uint8_t rx_buff[1];
+ size_t rx_size = 0;
+
+ /* Initialize CoreUARTapb with its base address, baud value. */
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200,
+ (DATA_8_BITS | NO_PARITY));
+ /* Initializes the Athena Processor */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Select CCM operation */
+ display_operation_choices();
+
+ for(;;)
+ {
+ /* Read input from UART terminal. */
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ switch(rx_buff[0])
+ {
+ case '1':
+ /* Perform Encryption using AES-128.*/
+ UART_send(&g_uart, aes_encrypt_select_msg,
+ sizeof(aes_encrypt_select_msg));
+
+ /* Authenticate and encrypt the input data.*/
+ perform_ccm_encrypt();
+
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '2':
+ /* Perform decryption using AES-128 */
+ UART_send(&g_uart, aes_decrypt_select_msg,
+ sizeof(aes_decrypt_select_msg));
+
+ /* Authenticate and decrypt the input data.*/
+ perform_ccm_decrypt();
+
+ display_option();
+ display_operation_choices();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/aesf5200.h
new file mode 100644
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calcontext.h
new file mode 100644
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calenum.h
new file mode 100644
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calini.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calini.h
new file mode 100644
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calpolicy.h
new file mode 100644
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/caltypes.h
new file mode 100644
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/config_user.h
new file mode 100644
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbg.h
new file mode 100644
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbgf5200.h
new file mode 100644
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/hash.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/hash.h
new file mode 100644
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/mac.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/mac.h
new file mode 100644
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100644
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100644
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/nrbg.h
new file mode 100644
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pk.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pk.h
new file mode 100644
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkx.h
new file mode 100644
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkxlib.h
new file mode 100644
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/shaf5200.h
new file mode 100644
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/sym.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/sym.h
new file mode 100644
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/utils.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/utils.h
new file mode 100644
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/x52cfg_user.h
new file mode 100644
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/README.md b/user-crypto/miv-rv32-ccm-services/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/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/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/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/user-crypto/miv-rv32-ccm-services/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-ccm-services/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal.h b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-ccm-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-ccm-services/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/user-crypto/miv-rv32-dsa-services/.cproject b/user-crypto/miv-rv32-dsa-services/.cproject
new file mode 100755
index 0000000..442ce3b
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/.cproject
@@ -0,0 +1,332 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/.gitignore b/user-crypto/miv-rv32-dsa-services/.gitignore
new file mode 100755
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/.project b/user-crypto/miv-rv32-dsa-services/.project
new file mode 100755
index 0000000..7c876b8
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-dsa-services
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-dsa-services/README.md b/user-crypto/miv-rv32-dsa-services/README.md
new file mode 100755
index 0000000..5022f8a
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/README.md
@@ -0,0 +1,164 @@
+PolarFire User Crypto ECDSA Services example
+================================================================================
+This Example Project demonstrates the usage of the User Crypto hardware block for
+the signature generation and verification using DSA service functions. It uses
+
+ - CALDSASignHash() is used to generate digital signature.
+ - CALDSAVerifyHash() is used to verify the digital signature.
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal followed by a menu system and instructions.
+
+This program displays the return data from User Crypto processor for digital
+signature generation and verification services.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Generate digital signature
+
+Select option '1' to generate a digital signature for DSA public-key cryptographic service.
+The signature generation function take following parameters as an input.
+1. *msg* -: message string
+2. *G* -: A generator point
+3. *K* -: A random per message parameter.
+4. *modulus P* -: A prime number P
+4. *modulus Q* -: A prime number Q
+5. *private_key X* -: private key to encrypt the message.
+
+The **CALDSASignHash()** function performs signature generation and after the
+successful generation program displays a success message along with
+generated signature set {R,S} on the UART terminal.
+
+### Verify digital signature
+
+Select *2* to verify the digital signature set {R,S} generated by DSA public key
+cryptographic services. The program takes a public key to verify the message signature
+along with other domain parameters.
+The **CALDSAVerifyHash()** function performs DSA signature verification and after
+successful completion it returns the result of verification process,an
+appropriate message will be displayed on the UART terminal based on the returned result.
+
+**NOTE:**
+The DSA signature Generation operation should be executed before executing
+ECDSA signature verification operation.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+**NOTE:**
+ 1. If you try to enter data values other than 0 - 9, a - f, A - F, an error
+ message will be displayed on the serial terminal.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality. You can use
+dsa_services.ttl Tera Term Macro script present in project directory for
+testing DSA Signature Services example project.
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
diff --git a/user-crypto/miv-rv32-dsa-services/dsa_services.ttl b/user-crypto/miv-rv32-dsa-services/dsa_services.ttl
new file mode 100755
index 0000000..94db886
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/dsa_services.ttl
@@ -0,0 +1,249 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+changedir '.'
+logopen "DSA_service.log" 0 0 0 1
+
+settitle 'PolarFire SoC MSS User Crypto DSA service'
+
+setsync 1
+
+;Clear screen
+clearscreen 0
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 1
+; INPUT
+; P =
+; a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae35885
+; 9d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c
+; 881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577
+; d9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f451829159
+; 8221fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a
+; 99be254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97b
+; bcaa07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb2969
+; 7d7d541348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877
+; Q = abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045
+; G =
+; 867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27
+; c2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed6
+; 8e79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d81
+; 4d1ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdf
+; b8098e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad105951
+; 6a1d45755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f7763884
+; 5b00e59ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6db
+; a64562085f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930
+
+;Msg =
+; ed9a64d3109ef8a9292956b946873ca4bd887ce624b81be81b82c69c67aaddf5655f70fe4768114db2834c71787f858e516
+; 5da1a7fa961d855ad7e5bc4b7be31b97dbe770798ef7966152b14b86ae35625a28aee5663b9ef3067cbdfbabd87197e5c84
+; 2d3092eb88dca57c6c8ad4c00a19ddf2e1967b59bd06ccaef933bc28e7
+;X = 6d4c934391b7f6fb6e19e3141f8c0018ef5726118a11064358c7d35b37737377
+;Y =
+; 1f0a5c75e7985d6e70e4fbfda51a10b925f6accb600d7c6510db90ec367b93bb069bd286e8f979b22ef0702f717a8755c18
+; 309c87dae3fe82cc3dc8f4b7aa3d5f3876f4d4b3eb68bfe910c43076d6cd0d39fc88dde78f09480db55234e6c8ca59fe270
+; 0efec04feee6b4e8ee2413721858be7190dbe905f456edcab55b2dc2916dc1e8731988d9ef8b619abcf8955aa960ef02b3f
+; 02a8dc649369222af50f1338ed28d667f3f10cae2a3c28a3c1d08df639c81ada13c8fd198c6dae3d62a3fe9f04c985c65f6
+; 10c06cb8faea68edb80de6cf07a8e89c00218185a952b23572e34df07ce5b4261e5de427eb503ee1baf5992db6d438b4743
+; 4c40c22657bc163e7953fa33eff39dc2734607039aadd6ac27e4367131041f845ffa1a13f556bfba2307a5c78f2ccf11298
+; c762e08871968e48dc3d1569d09965cd09da43cf0309a16af1e20fee7da3dc21b364c4615cd5123fa5f9b23cfc4ffd9cfdc
+; ea670623840b062d4648d2eba786ad3f7ae337a4284324ace236f9f7174fbf442b99043002f
+;K = 40b5cc685c3d1f59072228af9551683b5b8c8ff65240114ad2dacfccf3928057
+
+; OUTPUT
+;R = 7695698a14755db4206e850b4f5f19c540b07d07e08aac591e20081646e6eedc
+;S = 3dae01154ecff7b19007a953f185f0663ef7f2537f0b15e04fb343c961f36de2
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature Generation
+;-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+;select signature generation
+send '1'
+pause 1
+
+; Msg
+pause 1
+send 'ed9a64d3109ef8a9292956b946873ca4bd887ce624b81be81b82c69c67aaddf5655f70fe4768114db2834c71787f858e516'
+send '5da1a7fa961d855ad7e5bc4b7be31b97dbe770798ef7966152b14b86ae35625a28aee5663b9ef3067cbdfbabd87197e5c84'
+send '2d3092eb88dca57c6c8ad4c00a19ddf2e1967b59bd06ccaef933bc28e7'
+pause 1
+
+;G
+pause 4
+send '867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27c'
+send '2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed68e'
+send '79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d814d1'
+pause 4
+send 'ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdfb809'
+send '8e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad1059516a1d4'
+send '5755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f77638845b00e5'
+send '9ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6dba645620'
+send '85f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930'
+pause 4
+
+;K
+send '40b5cc685c3d1f59072228af9551683b5b8c8ff65240114ad2dacfccf3928057'
+pause 2
+
+;X
+send '6d4c934391b7f6fb6e19e3141f8c0018ef5726118a11064358c7d35b37737377'
+
+pause 4
+
+;P
+send 'a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae35885'
+send '9d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c'
+pause 4
+send '881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577d'
+send '9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f45182915982'
+send '21fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a99b'
+send 'e254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97bbcaa'
+send '07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb29697d7d5'
+send '41348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877'
+pause 4
+
+;Q
+send 'abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045'
+
+pause 4
+; send dummy
+send '1'
+pause 3
+
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature verification
+;-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+;select verification
+send '2'
+pause 1
+
+; send option 1 to automatically generate the public key
+send '1'
+pause 5
+
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 2
+; INPUT
+; P =
+; a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae35885
+; 9d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c
+; 881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577
+; d9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f451829159
+; 8221fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a
+; 99be254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97b
+; bcaa07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb2969
+; 7d7d541348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877
+; Q =
+; abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045
+; G =
+; 867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27
+; c2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed6
+; 8e79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d81
+; 4d1ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdf
+; b8098e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad105951
+; 6a1d45755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f7763884
+; 5b00e59ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6db
+; a64562085f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930
+; Msg =
+; c737d5ae248a96062d6afa8dcacc0384c5fbfb9d8b6052b52493c60d3edfc524b567b1f896e7447d0e24019403ed83e4889
+; c0c4de57c70fada6c8b5a09904350a44dfaf77d60af62de3edfd8760d077473f26df2837cfc2015f227dd7d351a5350f142
+; 8f2699fd3f518326fea8aef98fc4ea673130c8079fac3895fe856c77f8
+; X =
+; 40dbd496fc4644be7ccb24d9dc55895c1b923a05f4da5610589d564ee8aac33f
+; Y =
+; 6112d3cd3191d17dee7788f568815a0aab50006002c9de2bd1a9bba245ba02894b02e9247517ace698ae0a05176b62b3a02
+; 5a563dda8deb7f2fc3e177ae3477448d39ae4ebe7ae8ec65a4421f754667fd6d7c2eb93f1a18d3d1a6235736bcdb74746f4
+; 6d88e65dc07c2591e1f95dda5e5e20e105ee8b4ddcaaf36021290d6b6493671d8aafae145d9b90bec3cc60179bb8fc30f14
+; 3c575d5d861623721b6547d3aaaade455f05fef9318abcd29bd19b12c35ca756de5108c185ece4aa1bf1a8e38809797067b
+; d1f52b6cf2c415e73f9246bd5bfadd7b9a9d2b5369701e72147e22da7e092d9b578fb0c044a36effcbd709258500a00cff2
+; 30962c44225712fc43f9e802baead7f9cb46ab4931f663c6e3ed4082d59610f01741b5f24566b01b3e3933b29e028c54bd2
+; fc75b549fd05e64c58c9ae0ba417a9e98581db77be75233a42f771c99f0a49b494f0955202b19d6c740e866066104e463e6
+; 5e4bad9a081636d05367426153f04bcb2712186dca6834388e82520d34efd8a89313b2c7e60
+; K =
+; aa63e91cb3fa545c447a8b8309a569d48104e14d5d05b8951033ac8a7d711c3f
+
+; OUTPUT
+;R = 0041b1c756dd2e42714f9ee7edce21ea33ef49dbf452ccd9357d5f45ffab08f9
+;S = 102c6eaad38d39c0d036335ae19dd0d75e8dcabae59b120f69cbd2b5cf48abdb
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature Generation
+;-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+send '5'
+pause 1
+
+;select signature generation
+send '1'
+pause 1
+
+; Msg
+pause 1
+send 'c737d5ae248a96062d6afa8dcacc0384c5fbfb9d8b6052b52493c60d3edfc524b567b1f896e7447d0e24019403ed83e4889'
+send 'c0c4de57c70fada6c8b5a09904350a44dfaf77d60af62de3edfd8760d077473f26df2837cfc2015f227dd7d351a5350f142'
+send '8f2699fd3f518326fea8aef98fc4ea673130c8079fac3895fe856c77f8'
+pause 1
+
+;G
+pause 4
+send '867d5fb72f5936d1a14ed3b60499662f3124686ef108c5b3da6663a0e86197ec2cc4c9460193a74ff16028ac9441b0c7d27'
+send 'c2272d483ac7cd794d598416c4ff9099a61679d417d478ce5dd974bf349a14575afe74a88b12dd5f6d1cbd3f91ddd597ed6'
+send '8e79eba402613130c224b94ac28714a1f1c552475a5d29cfcdd8e08a6b1d65661e28ef313514d1408f5abd3e06ebe3a7d81'
+pause 4
+send '4d1ede316bf495273ca1d574f42b482eea30db53466f454b51a175a0b89b3c05dda006e719a2e6371669080d768cc038cdf'
+send 'b8098e9aad9b8d83d4b759f43ac9d22b353ed88a33723550150de0361b7a376f37b45d437f71cb711f2847de671ad105951'
+send '6a1d45755224a15d37b4aeada3f58c69a136daef0636fe38e3752064afe598433e80089fda24b144a462734bef8f7763884'
+send '5b00e59ce7fa4f1daf487a2cada11eaba72bb23e1df6b66a183edd226c440272dd9b06bec0e57f1a0822d2e00212064b6db'
+send 'a64562085f5a75929afa5fe509e0b78e630aaf12f91e4980c9b0d6f7e059a2ea3e23479d930'
+pause 4
+
+;K
+send 'aa63e91cb3fa545c447a8b8309a569d48104e14d5d05b8951033ac8a7d711c3f'
+pause 2
+
+;X
+send '40dbd496fc4644be7ccb24d9dc55895c1b923a05f4da5610589d564ee8aac33f'
+
+pause 4
+
+;P
+send 'a410d23ed9ad9964d3e401cb9317a25213f75712acbc5c12191abf3f1c0e723e2333b49eb1f95b0f9748d952f04a5ae35885'
+send '9d384403ce364aa3f58dd9769909b45048548c55872a6afbb3b15c54882f96c20df1b2df164f0bac849ca17ad2df63abd75c'
+pause 4
+send '881922e79a5009f00b7d631622e90e7fa4e980618575e1d6bd1a72d5b6a50f4f6a68b793937c4af95fc11541759a1736577d'
+send '9448b87792dff07232415512e933755e12250d466e9cc8df150727d747e51fea7964158326b1365d580cb190f45182915982'
+send '21fdf36c6305c8b8a8ed05663dd7b006e945f592abbecae460f77c71b6ec649d3fd5394202ed7bbbd040f7b8fd57cb06a99b'
+send 'e254fa25d71a3760734046c2a0db383e02397913ae67ce65870d9f6c6f67a9d00497be1d763b21937cf9cbf9a24ef97bbcaa'
+send '07916f8894e5b7fb03258821ac46140965b23c5409ca49026efb2bf95bce025c4183a5f659bf6aaeef56d7933bb29697d7d5'
+send '41348c871fa01f869678b2e34506f6dc0a4c132b689a0ed27dc3c8d53702aa584877'
+pause 4
+
+;Q
+send 'abc67417725cf28fc7640d5de43825f416ebfa80e191c42ee886303338f56045'
+
+pause 4
+; send dummy
+send '1'
+pause 3
+
+; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature verification
+;-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+;select verification
+send '2'
+pause 1
+
+; send option 1 to automatically generate the public key
+send '1'
+pause 5
+
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw Debug.launch b/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw Debug.launch
new file mode 100755
index 0000000..be235fe
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw attach.launch b/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw attach.launch
new file mode 100644
index 0000000..3a05909
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/miv-rv32-dsa-services hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/application/helper.c b/user-crypto/miv-rv32-dsa-services/src/application/helper.c
new file mode 100755
index 0000000..3be82f2
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/application/helper.c
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include
+#include
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length,
+ uint8_t reverse_buffer
+)
+{
+
+ uint32_t inc;
+
+
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+
+
+ if(reverse_buffer == 0)
+ {
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+
+
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+ }
+ /* if reverse_byte is true */
+ else
+ {
+ for(inc = byte_length ; inc > 0; inc -= 1)
+ {
+ if((inc < byte_length) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc - 1];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+ }
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count % 2) == 0)
+ {
+ ret_size = count / 2;
+ }
+ else
+ {
+ if(size != 1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count / 2) + 1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/application/helper.h b/user-crypto/miv-rv32-dsa-services/src/application/helper.h
new file mode 100755
index 0000000..0a2effe
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/application/helper.h
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+#define DATA_LENGTH_32_BYTES 32
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+extern UART_instance_t g_uart;
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length,
+ uint8_t reverse_buffer
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-dsa-services/src/application/main.c b/user-crypto/miv-rv32-dsa-services/src/application/main.c
new file mode 100644
index 0000000..165865e
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/application/main.c
@@ -0,0 +1,416 @@
+
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Application demonstrating the DSA cryptography service. Please see the
+ * Readme.md for more details.
+ *
+ */
+#include
+#include
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#include "helper.h"
+
+
+#define KEY_SIZE 32
+#define DATA_LENGTH_32_BYTES 32
+#define REVERSE_FALSE 0
+#define REVERSE_TRUE 1
+
+/*flag to verify that DSA Signature has been generated before verification */
+#define SIG_GEN_TRUE 1
+#define SIG_GEN_FALSE 0
+#define PARAM_WORD_SIZE 12
+/******************************************************************************
+ * User Crypto base address. This will be used in config_user.h in CAL.
+ *****************************************************************************/
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+************* PolarFire User Crypto DSA Service Example Project **************\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the DSA service to calculate\r\n\
+ a DSA signature on a provided message and also verifies the generated message\r\n\
+signature. \r\n";
+const uint8_t g_select_operation_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select the Cryptographic operation to perform:\r\n\
+ Press Key '1' to perform DSA signature generation \r\n\
+ Press Key '2' to perform DSA signature verification \r\n\
+------------------------------------------------------------------------------\r\n";
+const uint8_t dsa_generation_msg[] =
+"\r\n\
+******************************************************************************\r\n\
+ DSA Signature Generation\r\n\
+******************************************************************************\r\n" ;
+const uint8_t dsa_verification_msg[] =
+"\r\n\
+******************************************************************************\r\n\
+ DSA Signature verification\r\n\
+******************************************************************************\r\n";
+const uint8_t select_private_key_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select one of the following options:\r\n\
+ Press Key '1' to generate private key through CALECKeyPairGen() function \r\n\
+ Press Key '2' to get private key from the terateram macro. \r\n\
+------------------------------------------------------------------------------\r\n";
+
+const uint8_t select_public_key_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select one of the following options:\r\n\
+ Press Key '1' to generate public key through entered private_key \r\n\
+ Press Key '2' to get public key from the terateram macro. \r\n\
+------------------------------------------------------------------------------\r\n";
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t msg[] =
+ "\r\n Enter message (max size : 12 words): \r\n";
+static const uint8_t read_private_key[] =
+ "\r\n Enter private key x (max size : 12 words):\r\n";
+static const uint8_t read_public_key[] =
+ "\r\n Enter public key y (max size : 12 words):\r\n";
+static const uint8_t msg_gen_success[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r DSA signature generation successful \r\n";
+static const uint8_t msg_gen_fail[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r\n DSA signature generation fail \r\n";
+static const uint8_t msg_ver_success[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r DSA signature verification successful \r\n";
+static const uint8_t msg_ver_fail[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r\n DSA signature verification fail \r\n";
+static const uint8_t read_g[] =
+ "\r\n Enter the g parameter \r\n";
+
+static const uint8_t read_k[] =
+ "\r\n Enter the random value k (exactly 8 words ):\r\n";
+static const uint8_t read_p[] =
+ "\r\n Enter the prime number p (exactly 96 words):\r\n";
+static const uint8_t read_q[] =
+ "\r\n Enter the prime number q (exactly 96 words):\r\n";
+/*==============================================================================
+ Global Variables.
+ */
+ uint32_t __attribute__ ((section (".crypto_data"))) msg_g[32] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) k_g[8] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) p_g[96] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) pmu_g[97] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) r_g[8] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) s_g[8] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) g_g[96] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) x_g[8] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) y_g[96] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) q_g[8] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) qmu_g[9] = { 0x00 };
+ uint32_t __attribute__ ((section (".crypto_data"))) qlen_g = 0;
+ uint32_t __attribute__ ((section (".crypto_data"))) plen_g = 0;
+ uint16_t __attribute__ ((section (".crypto_data"))) msg_len = 0;
+ uint32_t __attribute__ ((section (".crypto_data"))) buffer[] = {0x00};
+
+/*==============================================================================
+ Local functions.
+ */
+static void dsa_sign(void);
+static void display_greeting(void);
+static void dsa_verify(void);
+
+/*==============================================================================
+ Performs signature generation for ECDSA public-key cryptography.
+ */
+ void dsa_verify(void)
+ {
+ SATR result;
+ uint8_t opt ;
+
+ get_input_data((uint8_t*)&opt, sizeof(opt),select_public_key_msg,
+ sizeof(select_public_key_msg));
+ if (opt == 1)
+ {
+ /* generate private and public key pair */
+ result = CALExpo(g_g, x_g, p_g, pmu_g, 8, plen_g/4, y_g);
+
+ if(SATR_SUCCESS == result)
+ {
+ CALPKTrfRes(SAT_TRUE);
+
+ /* display the generated public key */
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Public key generation successful \r\n" );
+ UART_send(&g_uart, (const uint8_t *)"\r\n public_key value : \r\n\r\n",
+ sizeof("\r\n public_key value : \r\n"));
+ display_output((uint8_t*)&y_g[0], sizeof(y_g),REVERSE_TRUE);
+ }
+ }
+ else
+ {
+ /* get public key y point */
+ get_input_data((uint8_t*)&y_g[0], sizeof(y_g), read_public_key,
+ sizeof(read_public_key));
+ /* adjust endianness */
+ CALWordReverse(y_g, sizeof(y_g));
+ CALByteReverseWord(y_g, sizeof(y_g));
+ }
+ /* generate public key*/
+ result = CALExpo(g_g, x_g, p_g, pmu_g, 8, plen_g/4, y_g);
+
+ result = CALPKTrfRes(SAT_TRUE);
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n Public key Generated y = g^x mod p \r\n ");
+
+
+ result = CALDSAVerifyHash(&msg_g[0], SATHASHTYPE_SHA384, msg_len, &g_g[0],
+ &y_g[0], &r_g[0], &s_g[0], &p_g[0], &pmu_g[0],q_g,
+ qmu_g, qlen_g/4, plen_g/4, SAT_TRUE,
+ X52CCR_DEFAULT);
+ if(SATR_SUCCESS == result)
+ {
+ result = CALPKTrfRes(SAT_TRUE);
+ switch(result)
+ {
+ case SATR_SUCCESS:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)msg_ver_success);
+ break;
+ case SATR_VERPARMR:
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n Signature R parameter must be in range [1,Q-1] ");
+ break ;
+ case SATR_VERPARMS:
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n Signature S parameter must be in range [1,Q-1] ");
+ break ;
+ case SATR_VERIFYFAIL:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)msg_ver_fail);
+ break ;
+ }
+ }
+ }
+
+
+void dsa_sign(void)
+{
+ SATR result;
+
+ /* Read message value. */
+ msg_len = get_input_data((uint8_t*)&msg_g, sizeof(msg_g), msg, sizeof(msg));
+
+ /* Read DSA value G parameter. */
+ get_input_data((uint8_t*)&g_g, sizeof(g_g), read_g,
+ sizeof(read_g));
+
+ /* Read random per-message value K parameter. */
+ get_input_data((uint8_t*)&k_g, sizeof(k_g), read_k,
+ sizeof(read_k));
+
+ /* Read Private key X parameter. */
+ get_input_data((uint8_t*)&x_g, sizeof(x_g), read_private_key,
+ sizeof(read_private_key));
+
+ /* Read module value P. */
+ plen_g = get_input_data((uint8_t*)&p_g, sizeof(p_g), read_p,
+ sizeof(read_p));
+
+ /* Read module value Q. */
+ qlen_g = get_input_data((uint8_t*)&q_g, sizeof(q_g), read_q,
+ sizeof(read_q));
+
+ /* Change the endianness of received parameter from UART terminal.*/
+ CALWordReverse((uint32_t*)&g_g, (sizeof(g_g)/4));
+ CALByteReverseWord((uint32_t*)&g_g, (sizeof(g_g)/4));
+ CALWordReverse((uint32_t*)&k_g, (sizeof(k_g)/4));
+ CALByteReverseWord((uint32_t*)&k_g,(sizeof(k_g)/4));
+ CALWordReverse((uint32_t*)&x_g, (sizeof(x_g)/4));
+ CALByteReverseWord((uint32_t*)&x_g, (sizeof(x_g)/4));
+ CALWordReverse((uint32_t*)&p_g, (sizeof(p_g)/4));
+ CALByteReverseWord((uint32_t*)&p_g, (sizeof(p_g)/4));
+ CALWordReverse((uint32_t*)&q_g, (sizeof(q_g)/4));
+ CALByteReverseWord((uint32_t*)&q_g, (sizeof(q_g)/4));
+
+ /* Initiate generation of pre-compute value for P. */
+ result = CALPreCompute((uint32_t*)&p_g[0], (uint32_t*)&pmu_g[0], 96u);
+ if(SATR_SUCCESS == result)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ }
+
+ /* Initiate generation of pre-compute value for Q. */
+ result = CALPreCompute((uint32_t*)&q_g[0], (uint32_t*)&qmu_g[0], 8u);
+ if(SATR_SUCCESS == result)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ }
+
+ /* Calculates a DSA signature with SCA countermeasures. */
+ result = CALDSASignHash(&msg_g[0], SATHASHTYPE_SHA384, msg_len, &g_g[0],
+ &k_g[0], &x_g[0], &p_g[0], &pmu_g[0], &q_g[0],
+ &qmu_g[0], qlen_g/4, plen_g/4, r_g, s_g, SAT_TRUE,
+ X52CCR_DEFAULT);
+
+ /* Display the generated signature. */
+ if(SATR_SUCCESS == result)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ switch(result)
+ {
+ case SATR_SUCCESS:
+
+ /* Display the generated signature in hex format. */
+ UART_send(&g_uart, msg_gen_success, sizeof(msg_gen_success));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n R value:\r\n\r\n");
+ display_output((uint8_t*)&r_g[0],sizeof(r_g),REVERSE_TRUE);
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n S value:\r\n\r\n");
+ display_output((uint8_t*)&s_g[0],sizeof(s_g),REVERSE_TRUE);
+ break;
+ case SATR_SIGNPARMK:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n k parameter must be in [1,q-1] \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+
+ case SATR_SIGNFAIL :
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+ }
+
+ }
+ else
+ {
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ }
+}
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Display the choice of cryptographic operation to perform.
+ */
+static void display_operation_choices(void)
+{
+ UART_send(&g_uart, g_select_operation_msg, sizeof(g_select_operation_msg));
+}
+
+/*==============================================================================
+ Display the Option to continue.
+ */
+static void display_option(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_buff[1];
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Press any key to continue.\r\n",
+ sizeof("\r\n Press any key to continue.\r\n"));
+ do
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ } while(0u == rx_size);
+}
+
+/*==============================================================================
+ * Perform DSA signature and verification sequentially
+ */
+/* Main function */
+void main(void)
+{
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0;
+ uint8_t sig_gen_success = SIG_GEN_FALSE ;
+
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200,
+ (DATA_8_BITS | NO_PARITY));
+
+ /* Initializes the Athena Processor */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Select cryptographic operation to perform */
+ display_operation_choices();
+
+ for(;;)
+ {
+ /* Read inputs from UART terminal. */
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ switch(rx_buff[0])
+ {
+ case '1':
+ /* Performs signature generation for DSA */
+ UART_send(&g_uart, dsa_generation_msg, sizeof(dsa_generation_msg));
+ dsa_sign();
+ sig_gen_success = SIG_GEN_TRUE ;
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '2':
+ /* Performs signature verification for DSA */
+ UART_send(&g_uart, dsa_verification_msg, sizeof(dsa_verification_msg));
+ if(sig_gen_success == SIG_GEN_TRUE)
+ {
+ dsa_verify();
+ }
+ else
+ {
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Please perform DSA signature Generation at least once before DSA verification \r\n ");
+ }
+ display_option();
+ display_operation_choices();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return;
+}
diff --git a/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100755
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/aesf5200.h
new file mode 100755
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calcontext.h
new file mode 100755
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calenum.h
new file mode 100755
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calini.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calini.h
new file mode 100755
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calpolicy.h
new file mode 100755
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/caltypes.h
new file mode 100755
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/config_user.h
new file mode 100755
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbg.h
new file mode 100755
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbgf5200.h
new file mode 100755
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/hash.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/hash.h
new file mode 100755
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/mac.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/mac.h
new file mode 100755
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100755
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100755
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/nrbg.h
new file mode 100755
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pk.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pk.h
new file mode 100755
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkx.h
new file mode 100755
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkxlib.h
new file mode 100755
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/shaf5200.h
new file mode 100755
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/sym.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/sym.h
new file mode 100755
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/utils.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/utils.h
new file mode 100755
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/x52cfg_user.h
new file mode 100755
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/README.md b/user-crypto/miv-rv32-dsa-services/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100755
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100755
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100755
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/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/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/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/user-crypto/miv-rv32-dsa-services/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-dsa-services/src/platform/hal/cpu_types.h
new file mode 100755
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal.h b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal.h
new file mode 100755
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_assert.h
new file mode 100755
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_irq.c
new file mode 100755
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_macros.h
new file mode 100755
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.S
new file mode 100755
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.h
new file mode 100755
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100755
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100755
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100755
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100755
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100755
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100755
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100755
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100755
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100755
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-dsa-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-dsa-services/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/user-crypto/miv-rv32-ecdsa-services/.cproject b/user-crypto/miv-rv32-ecdsa-services/.cproject
new file mode 100755
index 0000000..20076af
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/.cproject
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/.gitignore b/user-crypto/miv-rv32-ecdsa-services/.gitignore
new file mode 100755
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/.project b/user-crypto/miv-rv32-ecdsa-services/.project
new file mode 100755
index 0000000..c537dbe
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-ecdsa-services
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/README.md b/user-crypto/miv-rv32-ecdsa-services/README.md
new file mode 100755
index 0000000..8c66f19
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/README.md
@@ -0,0 +1,176 @@
+PolarFire User Crypto ECDSA Services example
+================================================================================
+This Example Project demonstrates the usage of the User Crypto hardware block for
+the signature generation and verification using ECDSA service functions. It uses
+**NIST-P384** elliptic curve for signature generation and verification.
+
+ - CALECDSASignHash() is used to generate digital signature.
+ - CALECDSAVerifyHash() is used to verify the digital signature.
+
+User can Experiment with different standard elliptic curves supported by user-
+crypto core by changing curve domain parameters.
+
+Here's the list of supported NIST-P curves
+- *P192*,*P224*,*P256*,*P384*,*P512*
+
+**NOTE** -: Athena core uses an Elliptic curve of the following format.
+
+> Y = X^3 - 3X + b
+
+The coefficient of X is fixed to a = -3 thus one should only choose a set of
+domain parameters which is based on the above mentioned elliptic curve.
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. The example project will display
+instructions over the serial port. To execute the particular service, user has
+to select the options as shown over the serial port.
+
+This program displays the return data from User Crypto processor for digital
+signature generation and verification services.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Generate digital signature
+
+Select '1' to generate a digital signature for ECDSA public-key cryptographic
+service. The signature generation function take following parameters as an input.
+1. *msg* -: message string
+2. *Gx,Gy* -: which is a generator point for NIST-P384 curve.
+3. *K* -: A random per message parameter.
+4. *modulus n* -: The order of cyclic group G
+5. *private_key* -: private key to encrypt the message.
+
+This project uses **SHA384** algorithm to generate a unique Hash value from the
+given message string. The **CALECDSASignHash()** function performs signature
+generation and after the successful generation program displays a success
+message along with generated signature set {R,S} on the UART terminal.
+
+*NOTE* -: **b** parameter of P384 elliptic is fixed as far as this example is concerned.
+
+### Verify digital signature:
+
+Select '2' to verify the digital signature set {R,S} generated by ECDSA public
+key cryptographic services. The program takes a public key to verify the message
+signature along with other domain parameters. The **CALECDSAVerifyHash()**
+function performs ECDSA signature verification and after successful completion
+it returns the result of verification process. An appropriate message will be
+displayed on the UART terminal based on the returned result.
+
+*NOTE* -: The ECDSA signature Generation operation should be executed before
+executing ECDSA signature verification operation.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality. You can use
+ecdsa_services.ttl Tera Term Macro script present in project directory for
+testing ECDSA Signature Services example project.
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/ecdsa_services.ttl b/user-crypto/miv-rv32-ecdsa-services/ecdsa_services.ttl
new file mode 100755
index 0000000..80a6dc6
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/ecdsa_services.ttl
@@ -0,0 +1,170 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+changedir '.'
+logopen "ECDSA_service.log" 0 0 0 1
+
+settitle 'PolarFire SoC MSS User Crypto ECDSA service'
+
+setsync 1
+
+;Clear screen
+clearscreen 0
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 00
+
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 1
+; INPUT
+; Xg = aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7
+; Yg = 3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F
+; Msg=54686973206973206f6e6c7920612074657374206d6573736167652e204974206973203438206279746573206c6f6e67
+; Hash H = b9210c9d7e20897ab86597266a9d5077e8db1b06f7220ed6ee75bd8b45db37891f8ba5550304004159f4453dc5b3f5a1
+; K = dc6b44036989a196e39d1cdac000812f4bdd8b2db41bb33af51372585ebd1db63f0ce8275aa1fd45e2d2a735f8749359
+; D = c838b85253ef8dc7394fa5808a5183981c7deef5a69ba8f4f2117ffea39cfcd90e95f6cbc854abacab701d50c1f3cf24
+
+; OUTPUT
+; r = a0c27ec8 93092dea 1e1bd2cc fed3cf94 5c8134ed 0c9f8131 1a0f4a05 942db8db
+; ed8dd59f 267471d5 462aa14f e72de856
+; s = 20ab3f45 b74f10b6 e11f96a2 c8eb694d 206b9dda 86d3c7e3 31c26b22 c987b753
+; 77265776 67adadf1 68ebbe80 3794a402
+;----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature Generation
+;-----------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+; select signature generation
+pause 1
+send '1'
+pause 2
+
+;Msg
+pause 1
+send '54686973206973206f6e6c7920612074657374206d6573736167652e204974206973203438206279746573206c6f6e67'
+pause 2
+
+;Gx
+pause 1
+send 'aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7'
+pause 2
+
+;Gy
+pause 1
+send '3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F'
+pause 2
+
+;K
+pause 1
+send 'dc6b44036989a196e39d1cdac000812f4bdd8b2db41bb33af51372585ebd1db63f0ce8275aa1fd45e2d2a735f8749359'
+pause 2
+
+;Modulus N
+pause 1
+send 'ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'
+
+; select option to enter private key
+send '2'
+pause 5
+
+;D
+pause 1
+send 'c838b85253ef8dc7394fa5808a5183981c7deef5a69ba8f4f2117ffea39cfcd90e95f6cbc854abacab701d50c1f3cf24'
+pause 2
+
+; send dummy
+send '1'
+pause 2
+
+;-------------------------------------------------------------------------------------------
+; signature verification
+;-------------------------------------------------------------------------------------------
+
+; select signature verification
+send '2'
+pause 2
+
+; select automatic public key generation
+send '1'
+pause 5
+
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 2
+; INPUT
+; Xg = aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7
+; Yg = 3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F
+; Msg= 4578616D706C65206F66204543445341207769746820502D333834
+; Hash H = 5AEA187D1C4F6E1B35057D20126D836C6ADBBC7049EE0299C9529F5E0B3F8B5A7411149D6C30D6CB2B8AF70E0A781E89
+; K = 2E44EF1F8C0BEA8394E3DDA81EC6A7842A459B534701749E2ED95F054F0137680878E0749FC43F85EDCAE06CC2F43FEF
+; D = F92C02ED629E4B48C0584B1C6CE3A3E3B4FAAE4AFC6ACB0455E73DFC392E6A0AE393A8565E6B9714D1224B57D83F8A08
+
+; OUTPUT
+; r = 30EA514FC0D38D8208756F068113C7CADA9F66A3B40EA3B313D040D9B57DD41A332795D02CC7D507FCEF9FAF01A27088
+; s = CC808E504BE414F46C9027BCBF78ADF067A43922D6FCAA66C4476875FBB7B94EFD1F7D5DBE620BFB821C46D549683AD8
+;----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Signature Generation
+;-----------------------------------------------------------------------------------------------------------------------------------------------------------------
+pause 1
+send '5'
+pause 2
+
+; select signature generation
+pause 1
+send '1'
+pause 2
+
+;Msg
+pause 1
+send '4578616D706C65206F66204543445341207769746820502D333834'
+send 13
+pause 2
+
+;Gx
+pause 1
+send 'aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760aB7'
+pause 2
+
+;Gy
+pause 1
+send '3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e5F'
+pause 2
+
+;K
+pause 1
+send '2E44EF1F8C0BEA8394E3DDA81EC6A7842A459B534701749E2ED95F054F0137680878E0749FC43F85EDCAE06CC2F43FEF'
+pause 2
+
+;Modulus N
+pause 1
+send 'ffffffffffffffffffffffffffffffffffffffffffffffffc7634d81f4372ddf581a0db248b0a77aecec196accc52973'
+
+; select option to enter private key
+send '2'
+pause 5
+
+;D
+pause 1
+send 'F92C02ED629E4B48C0584B1C6CE3A3E3B4FAAE4AFC6ACB0455E73DFC392E6A0AE393A8565E6B9714D1224B57D83F8A08'
+pause 2
+
+; send dummy
+send '1'
+pause 2
+
+;-------------------------------------------------------------------------------------------
+; signature verification
+;-------------------------------------------------------------------------------------------
+
+; select signature verification
+send '2'
+pause 2
+
+; select automatic public key generation
+send '1'
+pause 3
+
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw Debug.launch b/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw Debug.launch
new file mode 100755
index 0000000..18f709f
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw attach.launch b/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw attach.launch
new file mode 100644
index 0000000..423811a
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/miv-rv32-ecdsa-services hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/application/helper.c b/user-crypto/miv-rv32-ecdsa-services/src/application/helper.c
new file mode 100755
index 0000000..3be82f2
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/application/helper.c
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include
+#include
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length,
+ uint8_t reverse_buffer
+)
+{
+
+ uint32_t inc;
+
+
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+
+
+ if(reverse_buffer == 0)
+ {
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+
+
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+ }
+ /* if reverse_byte is true */
+ else
+ {
+ for(inc = byte_length ; inc > 0; inc -= 1)
+ {
+ if((inc < byte_length) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc - 1];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+ }
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count % 2) == 0)
+ {
+ ret_size = count / 2;
+ }
+ else
+ {
+ if(size != 1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count / 2) + 1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/application/helper.h b/user-crypto/miv-rv32-ecdsa-services/src/application/helper.h
new file mode 100755
index 0000000..0a2effe
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/application/helper.h
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+#define DATA_LENGTH_32_BYTES 32
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+extern UART_instance_t g_uart;
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length,
+ uint8_t reverse_buffer
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/application/main.c b/user-crypto/miv-rv32-ecdsa-services/src/application/main.c
new file mode 100755
index 0000000..e7bca98
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/application/main.c
@@ -0,0 +1,639 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Application demonstrating the ECDSA cryptography service. Please see
+ * the Readme.md for more details.
+ *
+ */
+#include
+#include
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#include "helper.h"
+
+
+#define KEY_SIZE 32
+#define DATA_LENGTH_32_BYTES 32
+#define REVERSE_FALSE 0
+#define REVERSE_TRUE 1
+
+/*flag to verify that ECDSA Signature has been generated before verification */
+#define SIG_GEN_TRUE 1
+#define SIG_GEN_FALSE 0
+#define PARAM_WORD_SIZE 12
+
+/******************************************************************************
+ * User Crypto base address. This will be used in config_user.h in CAL.
+ *****************************************************************************/
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+*************** PolarFire User Crypto ECDSA Service Example Project **********\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the ECDSA service to calculate\r\n\
+ an ECDSA signature on a provided message and also verifies the generated message \r\n\
+signature\r\n";
+const uint8_t g_select_operation_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select the Cryptographic operation to perform:\r\n\
+ Press Key '1' to perform ECDSA signature generation \r\n\
+ Press Key '2' to perform ECDSA signature verification \r\n\
+------------------------------------------------------------------------------\r\n";
+const uint8_t ecdsa_generation_msg[] =
+"\r\n\
+******************************************************************************\r\n\
+ ECDSA Signature Generation\r\n\
+******************************************************************************\r\n" ;
+const uint8_t ecdsa_verification_msg[] =
+"\r\n\
+******************************************************************************\r\n\
+ ECDSA Signature verification\r\n\
+******************************************************************************\r\n";
+const uint8_t select_private_key_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select one of the following options:\r\n\
+ Press Key '1' to generate private key through CALECKeyPairGen() function \r\n\
+ Press Key '2' to get private key from the terateram macro. \r\n\
+------------------------------------------------------------------------------\r\n";
+
+const uint8_t select_public_key_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select one of the following options:\r\n\
+ Press Key '1' to generate public key through entered private_key \r\n\
+ Press Key '2' to get public key from the terateram macro. \r\n\
+------------------------------------------------------------------------------\r\n";
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+static const uint8_t msg[] =
+ "\r\n Enter message (max size : 12 words): \r\n";
+static const uint8_t read_mod_n[] =
+ "\r\n Enter modulus value n for P-384 elliptic curve: \r\n";
+static const uint8_t read_private_key[] =
+ "\r\n Enter private key d (max size : 12 words):\r\n";
+static const uint8_t read_public_key_qx[] =
+ "\r\n Enter public key qx (max size : 12 words):\r\n";
+static const uint8_t read_public_key_qy[] =
+ "\r\n Enter public key qy (max size : 12 words):\r\n";
+static const uint8_t msg_gen_success[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r EC-DSA signature generation successful \r\n";
+static const uint8_t msg_gen_fail[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r\n EC-DSA signature generation fail \r\n";
+static const uint8_t msg_ver_success[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r EC-DSA signature verification successful \r\n";
+static const uint8_t msg_ver_fail[] = "\r\n\
+------------------------------------------------------------------------------\r\n\
+ \r\n EC-DSA signature verification fail \r\n";
+static const uint8_t read_Gx[] =
+ "\r\n Enter Curve generator point Gx for P-384 elliptic curve:\r\n";
+static const uint8_t read_Gy[] =
+ "\r\n Enter Curve generator point Gy for P-384 elliptic curve:\r\n";
+
+static const uint8_t read_k[] =
+ "\r\n Enter the random value k (exactly 12 words):\r\n";
+/*==============================================================================
+ Global Variables.
+ */
+uint32_t __attribute__ ((section (".crypto_data"))) msg_g[PARAM_WORD_SIZE] = {
+ 0x54686973,0x20697320,0x6f6e6c79,0x20612074,
+ 0x65737420,0x6d657373,0x6167652e,0x20497420,
+ 0x69732034,0x38206279,0x74657320,0x6c6f6e67
+};
+uint16_t msg_len = 0 ;
+uint8_t sig_gen_flag ;
+/* for simplicity the value of k is fixed */
+
+uint32_t __attribute__ ((section (".crypto_data"))) k_g[PARAM_WORD_SIZE] = {
+ 0xdc6b4403,0x6989a196,0xe39d1cda,0xc000812f,
+ 0x4bdd8b2d,0xb41bb33a,0xf5137258,0x5ebd1db6,
+ 0x3f0ce827,0x5aa1fd45,0xe2d2a735,0xf8749359
+};
+uint32_t __attribute__ ((section (".crypto_data"))) private_key_d[PARAM_WORD_SIZE] = {
+0x00};
+uint32_t __attribute__ ((section (".crypto_data"))) public_key_qx[PARAM_WORD_SIZE] = { 0x00 };
+uint32_t __attribute__ ((section (".crypto_data"))) public_key_qy[PARAM_WORD_SIZE] = { 0x00 };
+/* signature paramters */
+
+uint32_t __attribute__ ((section (".crypto_data"))) r_g[PARAM_WORD_SIZE] = {0x00};
+uint32_t __attribute__ ((section (".crypto_data"))) s_g[PARAM_WORD_SIZE] = {0x00};
+
+uint32_t __attribute__ ((section (".crypto_data"))) P384_Gx[PARAM_WORD_SIZE] = {
+ 0x72760aB7,0x3a545e38,0xbf55296c,0x5502f25d,
+ 0x82542a38,0x59f741e0,0x8ba79b98,0x6e1d3b62,
+ 0xf320ad74,0x8eb1c71e,0xbe8b0537,0xaa87ca22
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_Gy[PARAM_WORD_SIZE] = {
+ 0x90ea0e5F,0x7a431d7c,0x1d7e819d,0x0a60b1ce,
+ 0xb5f0b8c0,0xe9da3113,0x289a147c,0xf8f41dbd,
+ 0x9292dc29,0x5d9e98bf,0x96262c6f,0x3617de4a
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_n[PARAM_WORD_SIZE] = {
+
+ 0xccc52973, 0xecec196a, 0x48b0a77a, 0x581a0db2,
+ 0xf4372ddf, 0xc7634d81, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_npc[PARAM_WORD_SIZE+1] = {
+ 0x333ad68d, 0x1313e695, 0xb74f5885, 0xa7e5f24d,
+ 0x0bc8d220, 0x389cb27e, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_n1[PARAM_WORD_SIZE] = {
+
+ 0xccc52973, 0xecec196a, 0x48b0a77a, 0x581a0db2,
+ 0xf4372ddf, 0xc7634d81, 0xffffffff, 0xffffffff,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xfffffffE
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_npc1[PARAM_WORD_SIZE+1] = {
+ 0x333ad68d, 0x1313e695, 0xb74f5885, 0xa7e5f24d,
+ 0x0bc8d220, 0x389cb27e, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000001
+};
+uint32_t __attribute__ ((section (".crypto_data"))) P384_b[PARAM_WORD_SIZE] = {
+ 0xd3ec2aef, 0x2a85c8ed, 0x8a2ed19d, 0xc656398d,
+ 0x5013875a, 0x0314088f, 0xfe814112, 0x181d9c6e,
+ 0xe3f82d19, 0x988e056b, 0xe23ee7e4, 0xb3312fa7
+};
+
+/*==============================================================================
+ Local functions.
+ */
+static void ecdsa_sign(void);
+static void display_greeting(void);
+static void ecdsa_verify(void);
+
+/*==============================================================================
+ Performs signature generation for ECDSA public-key cryptography.
+ */
+void ecdsa_sign(void)
+{
+ SATR result;
+ uint16_t mod_len = 0;
+ uint8_t opt = 0;
+
+ /* Read message value. */
+ msg_len = get_input_data((uint8_t*)&msg_g[0], sizeof(msg_g), msg,
+ sizeof(msg));
+
+ /* Read Generator Gx. */
+ get_input_data((uint8_t*)&P384_Gx[0], sizeof(P384_Gx), read_Gx,
+ sizeof(read_Gx));
+
+ /* adjust endianness */
+ CALWordReverse(P384_Gx, sizeof(P384_Gx)/4);
+ CALByteReverseWord(P384_Gx, sizeof(P384_Gx)/4);
+
+ /* Read Generator Gy */
+ get_input_data((uint8_t*)&P384_Gy[0], sizeof(P384_Gy), read_Gy,
+ sizeof(read_Gy));
+
+ /* adjust endianness */
+ CALWordReverse(P384_Gy, sizeof(P384_Gy)/4);
+ CALByteReverseWord(P384_Gy, sizeof(P384_Gy)/4);
+
+ /* Read Random parameter K */
+ get_input_data((uint8_t*)&k_g[0], sizeof(k_g), read_k,
+ sizeof(read_k));
+
+ /* adjust endianness */
+ CALWordReverse(k_g, sizeof(k_g)/4);
+ CALByteReverseWord(k_g, sizeof(k_g)/4);
+
+ /* Read modulus value n (length of cyclic group) */
+ get_input_data((uint8_t*)&P384_n[0], sizeof(P384_n), read_mod_n,
+ sizeof(read_mod_n));
+
+ /* adjust endianness */
+ CALWordReverse(P384_n, sizeof(P384_n)/4);
+ CALByteReverseWord(P384_n, sizeof(P384_n)/4);
+
+ /*precompute of mod n */
+ result = CALPreCompute(P384_n,P384_npc,PARAM_WORD_SIZE);
+ if(SATR_SUCCESS == result)
+ {
+ /* transfer the result to P384_npc */
+ CALPKTrfRes(SAT_TRUE);
+ }
+ else
+ {
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n N Mod value is not correct ");
+ }
+ /* P384 curve b parameter is fixed for this example */
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Fixed B parameter for P384 curve: \r\n" );
+ display_output((uint8_t*)&P384_b[0],sizeof(P384_b),REVERSE_TRUE);
+
+ /* option to get the value of private key */
+ get_input_data((uint8_t*)&opt, sizeof(opt),select_private_key_msg,
+ sizeof(select_private_key_msg));
+ if (opt == 1)
+ {
+
+ /* copy the contents of P384_n to P384_n1 because we need mod -1 */
+ memcpy(P384_n1,P384_n,sizeof(P384_n));
+
+ /* search for first non zero word and subtract 1 from it */
+ for(int wc = 0 ; wc < PARAM_WORD_SIZE; wc++)
+ {
+ if(P384_n1[wc] != 0)
+ {
+ P384_n1[0] -= 1;
+ break;
+ }
+ else
+ {
+ continue ;
+ }
+ }
+
+ /* precompute of mod(N-1) */
+ result = CALPreCompute(P384_n1,P384_npc1,PARAM_WORD_SIZE);
+ if(SATR_SUCCESS == result)
+ {
+ /* transfer the result to P384_npc */
+ CALPKTrfRes(SAT_TRUE);
+ }
+ else
+ {
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n N-1 Mod value is not correct ");
+ }
+
+ /* generate private and public key pair */
+ result = CALECKeyPairGen(&k_g[0],P384_Gx,P384_Gy,P384_MOD,SAT_NULL,
+ P384_n1,P384_npc1,P384_b,private_key_d,public_key_qx,public_key_qy,12);
+
+ result = CALPKTrfRes(SAT_TRUE);
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Generated private key : \r\n" );
+ display_output((uint8_t*)&private_key_d[0],sizeof(private_key_d),REVERSE_TRUE);
+ }
+ else
+ {
+ get_input_data((uint8_t*)&private_key_d[0], sizeof(private_key_d), read_private_key,
+ sizeof(read_private_key));
+
+ /* adjust endianness */
+ CALWordReverse(private_key_d, sizeof(private_key_d)/4);
+ CALByteReverseWord(private_key_d, sizeof(private_key_d)/4);
+ }
+
+ /* Calculates ECDSA signature */
+ result = CALECDSASignHash(&msg_g[0], SATHASHTYPE_SHA384, msg_len, P384_Gx,
+ P384_Gy, (const uint32_t*)&k_g,
+ (const uint32_t*)&private_key_d, P384_b,
+ P384_MOD, SAT_NULL, P384_n, P384_npc, 12, r_g,
+ s_g, SAT_TRUE, X52CCR_DEFAULT);
+ if(SATR_SUCCESS == result)
+ {
+ result = CALPKTrfRes(SAT_TRUE);
+ switch(result)
+ {
+ case SATR_SUCCESS:
+
+ /* Display the generated signature in hex format. */
+ UART_send(&g_uart, msg_gen_success, sizeof(msg_gen_success));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n R value:\r\n\r\n");
+ display_output((uint8_t*)&r_g[0],sizeof(r_g),REVERSE_TRUE);
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n S value:\r\n\r\n");
+ display_output((uint8_t*)&s_g[0],sizeof(s_g),REVERSE_TRUE);
+ break;
+ case SATR_VALPARMX:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n X parameter not in range \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+ case SATR_VALPARMY:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Y parameter not in range \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break;
+
+ case SATR_VALPARMB:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n B parameter greater than modulus \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+
+ case SATR_VALIDATEFAIL :
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Generator point is not on the curve \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+
+ case SATR_SIGNPARMD:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n private_key parameter is not in range [1,N-1] \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+
+ case SATR_SIGNPARMK :
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n random parameter K is not in range [1,N-1] \r\n");
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+
+ case SATR_SIGNFAIL :
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ break ;
+ }
+
+ }
+ else
+ {
+ /* ECDSA signature generation fail */
+ UART_send(&g_uart, msg_gen_fail, sizeof(msg_gen_fail));
+ }
+}
+
+/*==============================================================================
+ Performs signature verification for ECDSA public-key cryptography.
+ */
+void ecdsa_verify(void)
+{
+ SATR result;
+ uint8_t opt = 0;
+
+ /* option to get public key */
+ get_input_data((uint8_t*)&opt, sizeof(opt),select_public_key_msg,
+ sizeof(select_public_key_msg));
+ if (opt == 1)
+ {
+ /* generate private and public key pair */
+ result = CALECMult(private_key_d,P384_Gx, P384_Gy, P384_b, P384_MOD, SAT_NULL,
+ 12, 0,public_key_qx, public_key_qy);
+
+ if(SATR_SUCCESS == result)
+ {
+ CALPKTrfRes(SAT_TRUE);
+
+ /* display the generated public key */
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Public key generation successful \r\n" );
+ UART_send(&g_uart, (const uint8_t *)"\r\n public_key_qx value : \r\n\r\n",
+ sizeof("\r\n public_key_qx value : \r\n"));
+ display_output((uint8_t*)&public_key_qx[0], sizeof(public_key_qx),REVERSE_TRUE);
+ UART_send(&g_uart, (const uint8_t *)"\r\n public_key_qy value: \r\n\r\n",
+ sizeof("\r\n public_key_qy value: \r\n"));
+ display_output((uint8_t*)&public_key_qy[0], sizeof(public_key_qy),REVERSE_TRUE);
+ }
+ }
+ else
+ {
+ /* get public key x point */
+ get_input_data((uint8_t*)&public_key_qx[0], sizeof(public_key_qx), read_public_key_qx,
+ sizeof(read_public_key_qx));
+
+ /* adjust endianness */
+ CALWordReverse(public_key_qx, sizeof(public_key_qx));
+ CALByteReverseWord(public_key_qx, sizeof(public_key_qx));
+
+ /* get public key y point */
+ get_input_data((uint8_t*)&public_key_qy[0], sizeof(public_key_qy), read_public_key_qy,
+ sizeof(read_public_key_qy));
+
+ /* adjust endianness */
+ CALWordReverse(public_key_qy, sizeof(public_key_qy));
+ CALByteReverseWord(public_key_qy, sizeof(public_key_qy));
+ }
+
+ // validate that public key is on the curve
+ result = CALECPtValidate(public_key_qx, public_key_qy, P384_b, P384_MOD, SAT_NULL,12);
+
+ if(SATR_SUCCESS == result)
+ {
+ result = CALPKTrfRes(SAT_TRUE);
+ switch(result)
+ {
+ case SATR_SUCCESS:
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Validation successful public key point is on the curve \r\n");
+ break;
+ case SATR_VALPARMX:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n X parameter not in range \r\n");
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n validation Fail \r\n");
+ break ;
+ case SATR_VALPARMY:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Y parameter not in range \r\n");
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n validation Fail \r\n");
+ break;
+ case SATR_VALPARMB:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n B parameter greater than modulus \r\n");
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n validation Fail \r\n");
+ break ;
+ case SATR_VALIDATEFAIL :
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n public key point is not on the curve \r\n");
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n validation Fail \r\n");
+ break ;
+ }
+
+ }
+ else
+ {
+ /* public key validation fail */
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n validation Fail \r\n");
+ }
+
+ result = CALECDSAVerifyHash(&msg_g[0], SATHASHTYPE_SHA384, msg_len, P384_Gx,
+ P384_Gy, public_key_qx,public_key_qy,
+ r_g,s_g, P384_b,
+ P384_MOD, SAT_NULL, P384_n, P384_npc, 12, 0, SAT_TRUE, X52CCR_DEFAULT);
+
+ /* Display the generated signature in hex format. */
+ if(SATR_SUCCESS == result)
+ {
+ result = CALPKTrfRes(SAT_TRUE);
+ switch(result)
+ {
+ case SATR_SUCCESS:
+
+ /* Display the generated signature in hex format. */
+ UART_send(&g_uart, msg_ver_success, sizeof(msg_ver_success));
+ break;
+ case SATR_VALPARMX:
+
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n X parameter not in range \r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+ case SATR_VALPARMY:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Y parameter not in range \r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break;
+
+ case SATR_VALPARMB:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n B parameter greater than modulus \r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_VERPARMR:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n R parameter Not in [1,N-1]\r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_VERPARMS:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n S parameter Not in [1,N-1]\r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_VALIDATEFAIL :
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n Generator point is not on the curve \r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_PAF:
+ UART_polled_tx_string(&g_uart, (uint8_t*)"\r\n\n point at infinity Generated \r\n");
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_VERIFYFAIL :
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+
+ case SATR_SIGNFAIL :
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ break ;
+ }
+
+ }
+ else
+ {
+ /* ECDSA signature generation fail */
+ UART_send(&g_uart, msg_ver_fail, sizeof(msg_ver_fail));
+ }
+}
+
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Display the choice of cryptographic operation to perform.
+ */
+static void display_operation_choices(void)
+{
+ UART_send(&g_uart, g_select_operation_msg, sizeof(g_select_operation_msg));
+}
+
+/*==============================================================================
+ Display the Option to continue.
+ */
+static void display_option(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_buff[1];
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Press any key to continue.\r\n",
+ sizeof("\r\n Press any key to continue.\r\n"));
+ do
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ } while(0u == rx_size);
+}
+
+/*==============================================================================
+ * Perform ECDSA signature and verification sequentially
+ */
+/* Main function */
+void main(void)
+{
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0;
+ uint8_t sig_gen_success = SIG_GEN_FALSE ;
+
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200,
+ (DATA_8_BITS | NO_PARITY));
+
+ /* Initializes the Athena Processor */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Select cryptographic operation to perform */
+ display_operation_choices();
+
+ for(;;)
+ {
+ /* Read inputs from UART terminal. */
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ switch(rx_buff[0])
+ {
+ case '1':
+ /* Performs signature generation for ECDSA */
+ UART_send(&g_uart, ecdsa_generation_msg, sizeof(ecdsa_generation_msg));
+ ecdsa_sign();
+ sig_gen_success = SIG_GEN_TRUE ;
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '2':
+ /* Performs signature verification for ECDSA */
+ UART_send(&g_uart, ecdsa_verification_msg, sizeof(ecdsa_verification_msg));
+ if(sig_gen_success == SIG_GEN_TRUE)
+ {
+ ecdsa_verify();
+ }
+ else
+ {
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Please perform ECDSA signature Generation at least once before ECDSA verification \r\n ");
+ }
+ display_option();
+ display_operation_choices();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return;
+}
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100755
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/aesf5200.h
new file mode 100755
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calcontext.h
new file mode 100755
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calenum.h
new file mode 100755
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calini.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calini.h
new file mode 100755
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calpolicy.h
new file mode 100755
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/caltypes.h
new file mode 100755
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/config_user.h
new file mode 100755
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbg.h
new file mode 100755
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbgf5200.h
new file mode 100755
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/hash.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/hash.h
new file mode 100755
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/mac.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/mac.h
new file mode 100755
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100755
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100755
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/nrbg.h
new file mode 100755
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pk.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pk.h
new file mode 100755
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkx.h
new file mode 100755
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkxlib.h
new file mode 100755
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/shaf5200.h
new file mode 100755
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/sym.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/sym.h
new file mode 100755
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/utils.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/utils.h
new file mode 100755
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/x52cfg_user.h
new file mode 100755
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/README.md b/user-crypto/miv-rv32-ecdsa-services/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100755
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100755
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100755
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/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/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/cpu_types.h
new file mode 100755
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal.h
new file mode 100755
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_assert.h
new file mode 100755
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_irq.c
new file mode 100755
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_macros.h
new file mode 100755
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.S
new file mode 100755
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.h
new file mode 100755
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100755
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100755
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100755
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100755
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100755
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100755
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100755
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100755
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100755
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-ecdsa-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-ecdsa-services/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/user-crypto/miv-rv32-key-agreement/.cproject b/user-crypto/miv-rv32-key-agreement/.cproject
new file mode 100644
index 0000000..c82262a
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/.cproject
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/.gitignore b/user-crypto/miv-rv32-key-agreement/.gitignore
new file mode 100644
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/.project b/user-crypto/miv-rv32-key-agreement/.project
new file mode 100644
index 0000000..76406e6
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-key-agreement
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-key-agreement/README.md b/user-crypto/miv-rv32-key-agreement/README.md
new file mode 100644
index 0000000..8ebd9be
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/README.md
@@ -0,0 +1,144 @@
+PolarFire User Crypto Key Agreement service
+================================================================================
+This example project demonstrates the use of the PolarFire User Crypto key
+agreement Services using the following functions
+
+ - CALPreCompute()
+ - CALExpo()
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal.This program displays the return shared secret key data from User
+Crypto processor.
+
+This example project demonstrates the use of User Cyrpto – key agreement service
+to derive the shared secret key. It is primarily used as a method of exchanging
+cryptography keys for use in symmetric encryption algorithms such as AES. This
+service reads the base value, modules, private key of user A, public key of user
+B, and derive the secret key, which can be used for encryption/decryption of
+data and also displayed on the UART terminal.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+**NOTE**:
+1. There is no direct function to calculate shared secret using Diffie-Hellman
+ key agreement algorithm.
+2. You must enter all input data as whole bytes. If you enter the 128-bit key
+ {1230...0} as 0x12 0x3 and press return, this will be treated as
+ byte0 = 0x12, byte1 = 0x30, byte2-127 = 0x00.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality. You can use
+RV32_Key_agreement.ttl Tera Term Macro script present in project directory for
+testing key agreement example project.
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/RV32_Key_agreement.ttl b/user-crypto/miv-rv32-key-agreement/RV32_Key_agreement.ttl
new file mode 100644
index 0000000..e7381ff
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/RV32_Key_agreement.ttl
@@ -0,0 +1,103 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+changedir '.'
+logopen "KEY_AGREEMENT.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto Key Agreement service'
+
+setsync 1
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+; INPUT
+; P =
+; a25cb1199622be09d9f473695114963cbb3b109f92df6da1b1dcab5e8511e9a117e2881f30a78f04d6a3472b8064eb6416c
+; dfd7bb8b9891ae5b5a1f1ee1da0cace11dab3ac7a50236b22e105dbeef9e45b53e0384c45c3078acb6ee1ca983511795801
+; da3d14fa9ed82142ec47ea25c0c0b7e86647d41e9f55955b8c469e7e298ea30d88feacf43ade05841008373605808a2f8f8
+; 910b195f174bd8af5770e7cd85380d198f4ed2a0c3a2f373436ae6ce9567846a79275765ef829abbc6171718f7746ebd167
+; d406e2546acdea7299194a613660d5ef721cd77e7722095c4ca42b29db3d4436325b47f850af05d411c7a95ccc54555c193
+; 384a6eeebb47e6f0f
+;
+; Q = a944d488de8c89567b602bae44478632604f8bf7cb4deb851cf6e22d
+; G =
+; 1e2b67448a1869df1ce57517dc5e797b62c5d2c832e23f954bef8bcca74489db6caed2ea496b52a52cb664a168374cb176d
+; dc4bc0068c6eef3a746e561f8dc65195fdaf12b363e90cfffdac18ab3ffefa4b2ad1904b45dd9f6b76b477ef8816802c7bd
+; 7cb0c0ab25d378098f5625e7ff737341af63f67cbd00509efbc6470ec38c17b7878a463cebda80053f36558a308923e6b41
+; f465385a4f24fdb303c37fb998fc1e49e3c09ce345ff7cea18e9cd1457eb93daa87dba8a31508fa5695c32ce485962eb183
+; 4144413b41ef936db71b79d6fe985c018ac396e3af25054dbbc95e56ab5d4d4b7b61a70670e789c336b46b9f7be43cf6eb0
+; e68b40e33a55d55cc
+; XstatCAVS = 74162ac74759e85654e0e7762c2cdd2689009b24dae06d0a85260b81
+; YstatCAVS =
+; 23ed27e3e655e0a15027d8e75dc97d72756875ff7caab2c3882f0461bacfe599e1391567f2f1406ba841b7ce366a7726ee1
+; f3b56912de4c11f83d8d4096fffe4290ebfe3ffc3c11e9d6a2a1683d16222504d188a2265d678892ed39feaa17aae98ef39
+; cbbce0a765ec9a16d79f369a65c47f93ecdf3a2c6f15e5d112dd197c9593532953a2518cf1c6d336b77ad20aba67e150c3e
+; 94037aced49d557d63c48958253c2dc0d66bec9d0bc93739f300d1e1785d58ce3b7a50e65b3742e4de26c3a3db3e66055ae
+; 59117464d8dcea7435a6a95396e595146f61cffe6f5650b2d5231f629966e54630ed80b7d6dc03144bf379cf85acf13dd28
+; 5a1ee2bab4fe996a2
+; XstatIUT = 8280294a47d4748d853da60d016d1b03320b64df43188c882204f371
+; YstatIUT =
+; 86c59d66dc53689cdc6b60ca7628afa58759b27ffa0856d0037d390d60c14d86385bde5ed5bc6f7e0ab8e5f07d08a47b648
+; abd10865d9f4c9ee7cf5f7982c63a52a33b96482a94b1ece4a99022ec4aa41c7453648089152093a84d16e16039d71db9aa
+; a2aa701f483f6297c4d2647079290a2b94c9bf9ecaa6715758135898504130e381795adf7352b37d1be696012a03dcea475
+; 0e963365a7698355364cbedf1715abcb31e3b2aa072dfe15ffd4c2e7d69c8ed7dbb138522536b5e74495724fe4e74b662b9
+; af8c5a35616b9dde39c80041cc6ac62aeae2b802f91b62e9be27dae8006797529db42b2ad8a16353ba6a5d25ea25d443126
+; 9ea6fc397de3f16ed
+;
+; OUTPUT
+; Z =
+; 59ae47dfd2893b37bb229b05f19ec181b8bc7bace31d0ac37b27e364ea4ca179bb574d91fc554009195ee13bfd3877baa54
+; ed390eab7aa3dfd6f3a35a776a80f58999d7931a9f0d842eb9bad51a24f2d052e56d09ade631f5e3ba64e957e4d583e20ad
+; 35d5336708482dd59b80a351e664a724cdf28a7796d2e93fffc7b113a8288be2b562af9dc3f980c917d56a723351b7f4be2
+; d7384b51f69335cf6a2fde5fa4f151be66529a4c8e8850b9c98dcae3a84d0ac231845e2b3771b9c5583960490994a58ff0d
+; 748333f92d835f2886ff26b81ebf4b7d7dd6d052d3f2f3062f137ef3fcab8c95771ad837b0af0378d75285126151db08fd0
+; cea5aa9933ffebc50
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+
+pause 1
+
+;G
+pause 1
+send '1e2b67448a1869df1ce57517dc5e797b62c5d2c832e23f954bef8bcca74489db6caed2ea496b52a52cb664a168374cb176dd'
+send 'c4bc0068c6eef3a746e561f8dc65195fdaf12b363e90cfffdac18ab3ffefa4b2ad1904b45dd9f6b76b477ef8816802c7bd7c'
+send 'b0c0ab25d378098f5625e7ff737341af63f67cbd00509efbc6470ec38c17b7878a463cebda80053f36558a308923e6b41f46'
+send '5385a4f24fdb303c37fb998fc1e49e3c09ce345ff7cea18e9cd1457eb93daa87dba8a31508fa5695c32ce485962eb1834144'
+send '413b41ef936db71b79d6fe985c018ac396e3af25054dbbc95e56ab5d4d4b7b61a70670e789c336b46b9f7be43cf6eb0e68b4'
+send '0e33a55d55cc'
+pause 5
+
+;XstatCAVS
+pause 2
+send '74162ac74759e85654e0e7762c2cdd2689009b24dae06d0a85260b81'
+
+;P
+pause 2
+send 'a25cb1199622be09d9f473695114963cbb3b109f92df6da1b1dcab5e8511e9a117e2881f30a78f04d6a3472b8064eb6416c'
+send 'dfd7bb8b9891ae5b5a1f1ee1da0cace11dab3ac7a50236b22e105dbeef9e45b53e0384c45c3078acb6ee1ca983511795801'
+pause 2
+send 'da3d14fa9ed82142ec47ea25c0c0b7e86647d41e9f55955b8c469e7e298ea30d88feacf43ade05841008373605808a2f8f8'
+send '910b195f174bd8af5770e7cd85380d198f4ed2a0c3a2f373436ae6ce9567846a79275765ef829abbc6171718f7746ebd167'
+pause 2
+send 'd406e2546acdea7299194a613660d5ef721cd77e7722095c4ca42b29db3d4436325b47f850af05d411c7a95ccc54555c193'
+send '384a6eeebb47e6f0f'
+
+;YstatIUT
+pause 2
+send '86c59d66dc53689cdc6b60ca7628afa58759b27ffa0856d0037d390d60c14d86385bde5ed5bc6f7e0ab8e5f07d08a47b648'
+send 'abd10865d9f4c9ee7cf5f7982c63a52a33b96482a94b1ece4a99022ec4aa41c7453648089152093a84d16e16039d71db9aa'
+pause 4
+send 'a2aa701f483f6297c4d2647079290a2b94c9bf9ecaa6715758135898504130e381795adf7352b37d1be696012a03dcea475'
+send '0e963365a7698355364cbedf1715abcb31e3b2aa072dfe15ffd4c2e7d69c8ed7dbb138522536b5e74495724fe4e74b662b9'
+send 'af8c5a35616b9dde39c80041cc6ac62aeae2b802f91b62e9be27dae8006797529db42b2ad8a16353ba6a5d25ea25d443126'
+pause 4
+send '9ea6fc397de3f16ed'
+send 13
+
+pause 10
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw Debug.launch b/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw Debug.launch
new file mode 100644
index 0000000..c0b696e
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw attach.launch b/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw attach.launch
new file mode 100644
index 0000000..a4a7540
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/miv-rv32-key-agreement hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/application/helper.c b/user-crypto/miv-rv32-key-agreement/src/application/helper.c
new file mode 100644
index 0000000..4a78569
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/application/helper.c
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+extern UART_instance_t g_uart;
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+)
+{
+ uint32_t inc;
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ clear_variable(src_ptr, 4);
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count%2) == 0)
+ {
+ ret_size = count/2;
+ }
+ else
+ {
+ if(size!=1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count/2)+1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ volatile uint8_t invalid_ip = 1u;
+ uint8_t dma_enable = 0;
+
+ const uint8_t invalid_ms[] = "\r\n Invalid input. ";
+
+ while(invalid_ip != 0)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(&dma_enable, 1, msg, msg_size);
+
+ if(dma_enable >= 2)
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+ else
+ {
+ invalid_ip = 0;
+ }
+ }
+
+ return dma_enable;
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/application/helper.h b/user-crypto/miv-rv32-key-agreement/src/application/helper.h
new file mode 100644
index 0000000..7f21b6e
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/application/helper.h
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-key-agreement/src/application/main.c b/user-crypto/miv-rv32-key-agreement/src/application/main.c
new file mode 100644
index 0000000..0e9c17b
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/application/main.c
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This example project demonstrates the usage of PolarFire User Crypto
+ * Diffie-Hellman Key Agreement services.
+ *
+ */
+#include
+#include
+#include
+#include "stdint.h"
+#include "helper.h"
+#include "hal/hal.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+
+/*private utility function */
+static SATR CAL_EXECUTE(SATR result) {
+
+ return (result == SATR_SUCCESS) ? CALPKTrfRes(SAT_TRUE) : result;
+}
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+******** PolarFire User Athena Key Agreement Service Example Project *********\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the PolarFire User Crypto \r\n\
+ Athena Key Agreement Service for generating shared secret key.\r\n";
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+/*==============================================================================
+ Global Variables.
+ */
+static uint8_t Pmod_2048[256] ={ 0x00 };
+static uint8_t G_2048[256] = { 0x00 };
+static uint32_t PrePmod_2048[65];
+static uint32_t PublicKey_A[100];
+static uint32_t SharedSecret[65];
+static uint8_t PublicKey_B[400] = { 0x00 };
+static uint8_t E_2048[28] = { 0x00 };
+
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Diffie-Hellman key agreement algorithm.
+ */
+static void dh_key_agreement(void)
+{
+ const uint8_t base_value_msg[] =
+ "\r\n Enter base value (G) 256 bytes: \r\n";
+ const uint8_t read_mod_param[] =
+ "\r\n Enter modulus value: \r\n";
+ const uint8_t read_private_key_usrA[] =
+ "\r\n Enter private key of user A: \r\n";
+ const uint8_t read_userB_public_key[] =
+ "\r\n Enter user B public key: \r\n";
+
+ /* Read base value value. */
+ get_input_data((uint8_t*)&G_2048, sizeof(G_2048), base_value_msg,
+ sizeof(base_value_msg));
+
+ /* Read private key of user A. i.e.puiExp parameter. */
+ get_input_data((uint8_t*)&E_2048, sizeof(E_2048), read_private_key_usrA,
+ sizeof(read_private_key_usrA));
+
+ /* Read modulus parameter. */
+ get_input_data((uint8_t*)&Pmod_2048, sizeof(Pmod_2048), read_mod_param,
+ sizeof(read_mod_param));
+
+ /* Read shared secret key from user B. */
+ get_input_data((uint8_t*)&PublicKey_B, sizeof(PublicKey_B),
+ read_userB_public_key, sizeof(read_userB_public_key));
+
+ /* Change the endianness of received parameter from UART terminal.*/
+ CALWordReverse((uint32_t*)&G_2048, 64);
+ CALByteReverseWord((uint32_t*)&G_2048, 64);
+ CALWordReverse((uint32_t*)&E_2048, 7);
+ CALByteReverseWord((uint32_t*)&E_2048, 7);
+ CALWordReverse((uint32_t*)&Pmod_2048, 64);
+ CALByteReverseWord((uint32_t*)&Pmod_2048, 64);
+ CALWordReverse((uint32_t*)&PublicKey_B, 64);
+ CALByteReverseWord((uint32_t*)&PublicKey_B, 64);
+
+ /* Initiate generation of pre-compute value. */
+ CAL_EXECUTE(CALPreCompute((uint32_t*)&Pmod_2048, PrePmod_2048, 64u));
+
+ /* Initiate modular exponentiation operation - Generate Public key for
+ * PARTY-A. */
+ CAL_EXECUTE(CALExpo((uint32_t*)&G_2048, (uint32_t*)&E_2048,
+ (uint32_t*)&Pmod_2048, PrePmod_2048, 7u, 64u,
+ PublicKey_A));
+
+ /* Generate shared secret key using PARTY-B public key. */
+ CAL_EXECUTE(CALExpo((uint32_t*)&PublicKey_B, (uint32_t*)&E_2048, SAT_NULL,
+ SAT_NULL, 7u, 64u, SharedSecret));
+
+ /* Display Shared secret key on UART terminal.*/
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Secret key value: \r\n",
+ sizeof("\r\n Secret key value:\r\n"));
+ CALWordReverse((uint32_t*)&SharedSecret, 64);
+ CALByteReverseWord((uint32_t*)&SharedSecret, 64);
+ display_output((uint8_t*)&SharedSecret[0], 256);
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+int main( void )
+{
+
+ /* 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));
+
+ /* Initializes the Athena Processor */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Calculate shared secret using Diffie-Hellman key agreement algorithm.*/
+ dh_key_agreement();
+
+ for(;;)
+ {
+ ;
+ }
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/aesf5200.h
new file mode 100644
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calcontext.h
new file mode 100644
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calenum.h
new file mode 100644
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calini.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calini.h
new file mode 100644
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calpolicy.h
new file mode 100644
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/caltypes.h
new file mode 100644
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/config_user.h
new file mode 100644
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbg.h
new file mode 100644
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbgf5200.h
new file mode 100644
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/hash.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/hash.h
new file mode 100644
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/mac.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/mac.h
new file mode 100644
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100644
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100644
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/nrbg.h
new file mode 100644
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pk.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pk.h
new file mode 100644
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkx.h
new file mode 100644
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkxlib.h
new file mode 100644
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/shaf5200.h
new file mode 100644
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/sym.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/sym.h
new file mode 100644
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/utils.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/utils.h
new file mode 100644
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/x52cfg_user.h
new file mode 100644
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/README.md b/user-crypto/miv-rv32-key-agreement/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/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/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/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/user-crypto/miv-rv32-key-agreement/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-key-agreement/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal.h b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-key-agreement/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-key-agreement/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/user-crypto/miv-rv32-keytree-services/.cproject b/user-crypto/miv-rv32-keytree-services/.cproject
new file mode 100644
index 0000000..d523f8c
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/.cproject
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/.gitignore b/user-crypto/miv-rv32-keytree-services/.gitignore
new file mode 100644
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/.project b/user-crypto/miv-rv32-keytree-services/.project
new file mode 100644
index 0000000..774b513
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-keytree-services
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-keytree-services/README.md b/user-crypto/miv-rv32-keytree-services/README.md
new file mode 100644
index 0000000..9faa683
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/README.md
@@ -0,0 +1,144 @@
+PolarFire User Crypto - Key Tree Services example
+================================================================================
+This example project demonstrates the use of following the PolarFire User Crypto
+Services functions:
+
+ - CALKeyTree()
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal followed by a menu system and instructions.
+
+Key tree service is used to derive a secret key from a secret value or values.
+This example project demonstrates the use of 256-bit production key, 128-bit
+nonce, 8-bit optype to derive secret key. This example project reads the key,
+nonce, and operation type from UART terminal and calls the **CALKeyTree()**
+function. The **CALKeyTree()** function derive a session key using a 128-bit or
+256-bit path nonce, size combined with a user-defined operation type. The output
+of this service is a eight 32-bit word that is stored in a user buffer as well
+displayed on the UART terminal.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality. You can use
+miv-rv32-key-tree.ttl Tera Term Macro script present in project directory for
+testing keytree services example project.
+
+**NOTE:**
+1. Tera Term Macros dont work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+**NOTE**:
+ 1. If you try to enter data values other than 0 - 9, a - f, A - F, an error
+ message will be displayed on the serial port terminal.
+ 2. NIST vector is not available to test key Tree service so only return value
+ of CALKeyTree() function is check to determine key service is successful or
+ not.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/miv-rv32-key-tree.ttl b/user-crypto/miv-rv32-keytree-services/miv-rv32-key-tree.ttl
new file mode 100644
index 0000000..f7044de
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/miv-rv32-key-tree.ttl
@@ -0,0 +1,73 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+changedir '.'
+logopen "Cryptography.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto AES-128'
+
+setsync 1
+
+;Clear screen
+clearscreen 0
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+;; Send Dummy
+send $0
+
+; ---------------------------------------------------------------------------------------------------------------
+; KEY DERIVATION SERVICES
+; ---------------------------------------------------------------------------------------------------------------
+; ---------------------------------------------------------------------------------------------------------------
+
+; INPUT
+; KEY = 2c82552b5e75eefbe716a1c377292232b2e281bd4d11060dfe3226218a0d4f8b
+; NONCE = 46A85E18A798BE38010549CA17983E0D8B7DD1B55B953FB2321A1D66910EB3B0
+; OPTION = 1
+; OUTPUT
+; SESSION_KEY = 8EA304523CD9E68D756451AE24A3B114
+; ␀ A75AEF0EA52483DC87AF2DAB422EA974
+; ---------------------------------------------------------------------------------------------------------------
+
+;key
+send '2c82552b5e75eefbe716a1c377292232b2e281bd4d11060dfe3226218a0d4f8b'
+pause 1
+
+;user option
+send '1'
+pause 2
+
+;select send path nonce
+send '1'
+pause 2
+
+;enter nonce
+send '46A85E18A798BE38010549CA17983E0D8B7DD1B55B953FB2321A1D66910EB3B0'
+pause 10
+
+;----------------------------------------------------------------------------------
+; USE AUTO GENERATED NONCE
+;---------------------------------------------------------------------------------
+
+;key
+send '2c82552b5e75eefbe716a1c377292232b2e281bd4d11060dfe3226218a0d4f8b'
+pause 1
+
+;user option
+send '1'
+pause 2
+
+;select send path nonce
+send '2'
+pause 2
+
+
+
+logclose
diff --git a/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw Debug.launch b/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw Debug.launch
new file mode 100644
index 0000000..621dc90
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw attach.launch b/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw attach.launch
new file mode 100644
index 0000000..f63546a
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/miv-rv32-keytree-services hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/application/helper.c b/user-crypto/miv-rv32-keytree-services/src/application/helper.c
new file mode 100644
index 0000000..4a78569
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/application/helper.c
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function for PolarFire User Crypto- Cryptography service example.
+ *
+ */
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "helper.h"
+
+extern UART_instance_t g_uart;
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+
+/*==============================================================================
+ Function to clear local variable and array.
+ */
+static void clear_variable(uint8_t *p_var, uint16_t size)
+{
+ uint16_t inc;
+
+ for(inc = 0; inc < size; inc++)
+ {
+ *p_var = 0x00;
+ p_var++;
+ }
+}
+
+/*==============================================================================
+ Function to get the input data from user.
+ */
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint16_t count = 0u;
+
+ /* Clear the memory location. */
+ clear_variable(location, size);
+
+ /* Read data from UART terminal. */
+ count = get_data_from_uart(location, size, msg, msg_size);
+
+ return count;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ uint8_t status = 0u;
+ const uint8_t invalid_ms[] = "\r\n Invalid key type. ";
+
+ if(status == VALID)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(location, size, msg, msg_size);
+ }
+ else
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+}
+
+/*==============================================================================
+ Convert ASCII value to hex value.
+ */
+uint8_t convert_ascii_to_hex(uint8_t* dest, const uint8_t* src)
+{
+ uint8_t error_flag = 0u;
+
+ if((*src >= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+)
+{
+ uint32_t inc;
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ clear_variable(src_ptr, 4);
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count%2) == 0)
+ {
+ ret_size = count/2;
+ }
+ else
+ {
+ if(size!=1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count/2)+1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ volatile uint8_t invalid_ip = 1u;
+ uint8_t dma_enable = 0;
+
+ const uint8_t invalid_ms[] = "\r\n Invalid input. ";
+
+ while(invalid_ip != 0)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(&dma_enable, 1, msg, msg_size);
+
+ if(dma_enable >= 2)
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+ else
+ {
+ invalid_ip = 0;
+ }
+ }
+
+ return dma_enable;
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/application/helper.h b/user-crypto/miv-rv32-keytree-services/src/application/helper.h
new file mode 100644
index 0000000..7f21b6e
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/application/helper.h
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13u
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-keytree-services/src/application/main.c b/user-crypto/miv-rv32-keytree-services/src/application/main.c
new file mode 100644
index 0000000..e88cd65
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/application/main.c
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This example project demonstrates the usage of PolarFire User Crypto
+ * key tree services.
+ *
+ */
+#include
+#include
+#include
+#include "stdint.h"
+#include "helper.h"
+#include "hal/hal.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include "drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h"
+#include "drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h"
+
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+
+#define DATA_LENGTH_32_BYTES 32
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+************* PolarFire User Crypto Key Tree Example Project *****************\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the User Crypto Key Tree service.\r\n";
+
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+const uint8_t read_key_input[] =
+"\r\n Enter the 256 bit key to be used: \r\n";
+const uint8_t read_op_type[] =
+"\r\n Enter user operation type:\r\n";
+const uint8_t read_path_nonce_input[] =
+"\r\n Enter the 256 bit path nonce: \r\n";
+const uint8_t path_nonce_option[] =
+"\r\n\r\n\
+--------------------------------------------------------------------------------\r\n\
+1. Press 1 to enter 256 bit path nonce value \r\n\
+2. press 2 to generate 256 bit path nonce \r\n ";
+
+
+
+/*==============================================================================
+ Key Tree service
+ */
+void keytree(void)
+{
+ uint8_t status = 0x00u;
+ uint32_t key[8] = {0x00};
+ uint8_t op_type = 0;
+ uint8_t opt = 0 ;
+ uint8_t path_nonce[NONCE_SERVICE_RESP_LEN] = {0x00};
+ uint32_t g_key_out[100] = {0x00};
+
+ /* Read the 32 bytes of key input data from UART terminal. */
+ get_input_data((uint8_t*)&key[0], sizeof(key), read_key_input,
+ sizeof(read_key_input));
+
+ /* Read the 1 bytes of operation type data from UART terminal. */
+ get_input_data(&op_type, sizeof(op_type), read_op_type, sizeof(read_op_type));
+
+ /* As bPathSizeSel is set to SAT_TRUE, read the 16 bytes of path nonce
+ * input data from UART terminal.
+ */
+ get_input_data(&opt, sizeof(opt), path_nonce_option, sizeof(path_nonce_option));
+
+ if( opt != 1 )
+ {
+
+ SYS_init((unsigned int) CORESYS_SERV_BASE_ADDR);
+
+ status = SYS_nonce_service(path_nonce, 0);
+ if (status == SYS_SUCCESS)
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\nGenerated Path_Nonce: \r\n");
+ display_output((uint8_t*)&path_nonce[0], DATA_LENGTH_32_BYTES);
+ }
+ else
+ {
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_polled_tx_string(&g_uart,(uint8_t*)"\r\n Error In path Nonce generation \r\n");
+ }
+ }
+ else
+ {
+
+ get_input_data((uint8_t*)&path_nonce[0], sizeof(path_nonce), read_path_nonce_input,
+ sizeof(read_path_nonce_input));
+
+ /* Change the endianness of data received from UART terminal. */
+ CALWordReverse((uint32_t*)&path_nonce, (sizeof(path_nonce)/4));
+ CALByteReverseWord((uint32_t*)&path_nonce, (sizeof(path_nonce)/4));
+ }
+
+
+ /* Change the endianness of data received from UART terminal. */
+ CALWordReverse((uint32_t*)&key, (sizeof(key)/4));
+ CALByteReverseWord((uint32_t*)&key, (sizeof(key)/4));
+
+ /* Derive a secret key */
+ status = CALKeyTree(1, key, op_type, (uint32_t*)&path_nonce[0], g_key_out);
+
+ /* Display the secret key in hex format. */
+ if(SATR_SUCCESS == status)
+ {
+ status = CALPKTrfRes(SAT_TRUE);
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Key tree successful \
+ \r\n Secret key:\r\n", sizeof("\r\n Key tree successful \
+ \r\n Secret key:\r\n"));
+ display_output((uint8_t*)&g_key_out[0], DATA_LENGTH_32_BYTES);
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Key tree service fail\r\n",
+ sizeof("\r\n Key tree service fail\r\n"));
+ }
+}
+
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+int main( void )
+{
+
+ uint8_t rx_buff[1];
+ size_t rx_size = 0;
+ /* 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));
+
+ /* Initializes the Athena Processor */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Perform Key tree */
+
+ for(;;)
+ {
+
+ keytree();
+ }
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/aesf5200.h
new file mode 100644
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calcontext.h
new file mode 100644
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calenum.h
new file mode 100644
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calini.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calini.h
new file mode 100644
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calpolicy.h
new file mode 100644
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/caltypes.h
new file mode 100644
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/config_user.h
new file mode 100644
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbg.h
new file mode 100644
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbgf5200.h
new file mode 100644
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/hash.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/hash.h
new file mode 100644
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/mac.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/mac.h
new file mode 100644
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100644
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100644
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/nrbg.h
new file mode 100644
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pk.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pk.h
new file mode 100644
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkx.h
new file mode 100644
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkxlib.h
new file mode 100644
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/shaf5200.h
new file mode 100644
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/sym.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/sym.h
new file mode 100644
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/utils.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/utils.h
new file mode 100644
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/x52cfg_user.h
new file mode 100644
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/README.md b/user-crypto/miv-rv32-keytree-services/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/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/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/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/user-crypto/miv-rv32-keytree-services/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-keytree-services/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal.h b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-keytree-services/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-keytree-services/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/user-crypto/miv-rv32-message-authentication/.cproject b/user-crypto/miv-rv32-message-authentication/.cproject
new file mode 100644
index 0000000..ba31722
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/.cproject
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/.gitignore b/user-crypto/miv-rv32-message-authentication/.gitignore
new file mode 100644
index 0000000..f1b6b72
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/.gitignore
@@ -0,0 +1,3 @@
+/.settings/
+/*miv-rv32-imc-debug*/
+/*miv-rv32-imc-release*/
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/.project b/user-crypto/miv-rv32-message-authentication/.project
new file mode 100644
index 0000000..b7a2b33
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/.project
@@ -0,0 +1,26 @@
+
+
+ miv-rv32-message-authentication
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/user-crypto/miv-rv32-message-authentication/README.md b/user-crypto/miv-rv32-message-authentication/README.md
new file mode 100644
index 0000000..2620ff3
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/README.md
@@ -0,0 +1,195 @@
+PolarFire User Crypto - Message Authentication And Hash Service Example
+================================================================================
+This example project demonstrates the use of the following PolarFire User Crypto
+Services functions:
+
+ - CALSymEncAuth()
+ - CALSymEncAuthDMA()
+ - CALMAC()
+ - CALMACDMA()
+ - CALHash()
+ - CALHashDMA()
+
+The User Crypto message authentication service provides a way to ensure the
+message integrity and to confirm that the message came from the stated sender
+(its authenticity). This example project demonstrate the use of MAC services
+to generate message authenticate code, authenticated encryption (the input
+message), and hash service to covert data of arbitrary length to a fixed length.
+
+There are two 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:
+
+ - miv-rv32-imc-debug
+ - miv-rv32-imc-release
+
+Mi-V Soft Processor
+--------------------------------------------------------------------------------
+This example uses Mi-V SoftProcessor MiV_RV32.The design is built for debugging
+MiV_RV32 through the PolarFire FPGA programming JTAG port using a FlashPro5.
+To achieve this the CoreJTAGDebug IP is used to connect to the JTAG port of the
+MiV_RV32.
+
+All the platform/design specific definitions such as peripheral base addresses,
+system clock frequency etc. are included in fpga_design_config.h. The
+fpga_design_config.h is located at the root folder of this project.
+
+The Mi-V Soft Processor MiV_RV32 firmware projects needs the miv_rv32_hal and
+the hal firmware(RISC-V HAL).
+
+The RISC-V HAL is available at GitHub [Mi-V-Soft-RISC-V](https://mi-v-ecosystem.github.io/redirects/platform).
+
+How to use this example
+--------------------------------------------------------------------------------
+This example project is targeted at a MIV_RV32 design running on a PolarFire-Eval-Kit
+connected via a USB-UART serial cable to a host PC running a terminal emulator
+such as TeraTerm or Putty configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control.
+
+Run the example project using a debugger. A greeting message will appear over the
+UART terminal followed by a menu system and instructions.
+
+This program displays the return data from User Crypto processor for message
+authentication and hash service.
+
+fpga_design_config (formerly known as hw_config.h)
+--------------------------------------------------------------------------------
+The SoftConsole project targeted for Mi-V processors now use an improved
+directory structure. 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.
+
+### Data Authenticated Encryption Using AES 256-bit key
+
+Select option '1' to perform authenticated encryption using Galois/counter mode (GCM)
+algorithm. This example project reads the 256 bit key, IV, 16 bytes plain text,
+and additional authentication data (AAD) from UART terminal and calls the
+**CALSymEncAuth()** or **CALSymEncAuthDMA()** function. This function performs
+authenticated encryption with associated data for confidentiality and integrity.
+The plain text is both encrypted and used in computation of message
+authentication code according to the **SATSYMTYPE_AES256** encryption algorithm and
+GCM mode. Both the encrypted data and tag are displayed on UART terminal.
+
+**NOTE** -:
+ In Case of GCM, in place of IV paramter user has to pass JO value which is calculated
+ according to the algorithm
+ mentioned in the following document.
+ [document](http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf)
+
+Generate MAC Using **HMACSHA-256** Algorithms
+Press 2 to calculate message authentication code using HMAC SHA-256 algorithms.
+This example project reads the key and message from UART terminal and calls the
+**CALMAC()** or **CALMACDMA()** function. The **CALMAC()** and **CALMACDMA()** functions
+calculate the MAC for the message based on SHA256 algorithm and the secret key.
+The calculated MAC is also displayed on UART terminal.
+
+Generate MAC Using AES-CMAC-256 Algorithms
+Press 3 to calculated message authentication code using AES-CMAC-256 algorithms.
+This example project reads the key and message from UART terminal and calls
+the CALMAC function. The **CALMAC()** functions calculates the MAC for the message
+based on AES CMAC 256 algorithm and the secret key. The calculated MAC is also
+displayed on UART terminal.
+NOTE:
+ MAC computation using DMA (i.e. **CALMACDMA** function) doesn’t support
+ **AES-CMAC-256** Algorithm.
+
+Hashing
+Press 4 to perform hashing. This service reads 64 bytes of message value and
+performs the hash operation using SHA-256 hash algorithm on the stored data.
+The hash results are stored at user memory location and also displayed on UART
+terminal.
+
+### Configurations
+
+The CAL library needs a config_user.h containing the configuration data.
+This application provides following settings as per CAL requirement
+ 1. A variable which provides the base address of the User Crypto hardware block
+ is defined in main.c
+
+ `uint32_t g_user_crypto_base_addr = 0x62000000UL;`
+
+ 2. A symbol INC_STDINT_H is defined in project preprocessor setting.
+ For more detail, please refer to caltypes.h file present in CAL folder.
+
+**NOTE**:
+ 1. If you try to enter data values other than 0 - 9, a - f, A - F, an error
+ message will be displayed on the serial terminal.
+ 2. You must enter all input data as whole bytes. If you enter the 128-bit key
+ {1230...0} as 0x12 0x3 and press return, this will be treated as
+ byte0 = 0x12, byte1 = 0x30, byte2-127 = 0x00.
+
+### Test script
+
+A test script is provided with this example which automatically enters the NIST
+vectors and associated data to verify the functionality.
+
+The following Tera Term macro scripts are present in "script" folder present.
+You can use these script for testing Message Authentication and Hashing
+services.
+1. MAC-gcm_msg_auth.ttl - Data Authenticated Encryption
+2. MAC-hmac_aes_cmac_256.ttl - Generate MAC Using AES-CMAC-256 Algorithms
+3. MAC-hmac_sha_256.ttl - Generate MAC Using HMAC SHA-256 Algorithms
+4. SHA-256.ttl - Hashing
+
+**NOTE:**
+1. Tera Term Macros don’t work with Windows 10 build 14393.0. You should update
+ to Windows 10 build 14393.0.105 or [later.](https://osdn.net/ticket/browse.php?group_id=1412&tid=36526)
+2. Before running Tera Term Macro script, set language as English
+ (Setup->General->Language). Also setup transmit delay in (Setup->Serial port)
+ to 5msec/char and 5msec/line.
+3. By default, Tera Term log will be stored in Tera Term installation Directory.
+
+## Target hardware
+
+This project was tested on PolarFire-Eval-Kit with CFG4 configuration of the
+MIV_RV32 design available [here](https://github.com/Mi-V-Soft-RISC-V/PolarFire-Eval-Kit/tree/main/Libero_Projects)
+
+All the design specific definitions such as peripheral base addresses, system
+clock frequency etc. are included in fpga_design_config.h.
+
+The firmware projects needs the HAL and the MIV_RV32 HAL firmware components.
+
+This example project can be used with another design using a different hardware
+configurations. This can be achieved by overwriting the content of this example
+project's "fpga_design_config.h" file with the correct data per your Libero design.
+
+### Booting the system
+
+Currently the example project is configured to use FlashPro debugger to execute
+from LSRAM in both Debug and Release mode.
+
+In the release mode build configuration, following setting is used
+`--change-section-lma *-0x80000000` under
+Tool Settings > Cross RISCV GNU Create Flash Image > General > Other flags.
+
+This will allow you to attach the release mode executable as the memory
+initialization client in Libero when you want to execute it from non-volatile memory.
+
+## Silicon revision dependencies
+
+This example is tested on PolarFire MPF300TS device.
+
+### CAL library src
+
+To obtain the CAL source code and a SoftConsole project to generate the CAL
+library archive file (*.a) refer [SoftConsole Documentation](https://mi-v-ecosystem.github.io/SoftConsole-Documentation/SoftConsole-v2021.3/using_softconsole/other.html#crypto-application-library).
+The CAL source code is bound by license agreement and it will be available as
+part of the SoftConsole installation if the CAL specific license was agreed
+while installing it.
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw Debug.launch b/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw Debug.launch
new file mode 100644
index 0000000..bd7b1a5
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw Debug.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw attach.launch b/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw attach.launch
new file mode 100644
index 0000000..f16d645
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/miv-rv32-message-authentication hw attach.launch
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/user-crypto/miv-rv32-message-authentication/scripts/MAC-gcm_msg_auth.ttl b/user-crypto/miv-rv32-message-authentication/scripts/MAC-gcm_msg_auth.ttl
new file mode 100644
index 0000000..b2c8ce6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/scripts/MAC-gcm_msg_auth.ttl
@@ -0,0 +1,97 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+changedir '.'
+logopen "MAC_gcm_msg_auth.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto MAC service'
+
+setsync 1
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+;press any key
+send '5'
+pause 1
+
+; -------------------------------------------------------------------------------
+; INPUT
+; Key = 96ac126b5b0ed0890b893657afa4c274ce300cb480cce961c27ddbc61e30783c
+; IV = ee9e54a316ced1374a13ca2e00000001
+; PT = b4786d6bda2dd17690f5b0df362f539c54e7e1cd2cd0ac1f0acfaa51d673095729f88db1b6dd54be0b62d349e56557aa4e4980
+; AAD = 396d0892aff3212995e8f564083a0972
+; OUTPUT
+; CT = df5af7ef15164d9faf062ab23356f7c4313bb9b05612de9e051ec31af83d7ff9f34e51143dfd43ab84a38f8950208653f1ff54
+; Tag = 9516b2653b1b06562bfca914
+; -----------------------------------------------------------------------------
+
+;DMA enabled Test case 1
+send '1'
+pause 2
+
+;key
+send '96ac126b5b0ed0890b893657afa4c274ce300cb480cce961c27ddbc61e30783c'
+pause 2
+
+;IV
+send 'ee9e54a316ced1374a13ca2e00000001'
+pause 1
+
+;PT
+send 'b4786d6bda2dd17690f5b0df362f539c54e7e1cd2cd0ac1f0acfaa51d673095729f88db1b6dd54be0b62d349e56557aa4e4980'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '396d0892aff3212995e8f564083a0972'
+pause 1
+send 13
+pause 1
+
+;Enable DMA
+send '1'
+pause 5
+
+;Press any key to continue
+send '6'
+
+; -----------------------------------------------------------------------------
+;DMA disabled Test case 2
+send '1'
+pause 2
+
+;key
+send '96ac126b5b0ed0890b893657afa4c274ce300cb480cce961c27ddbc61e30783c'
+pause 2
+
+;IV
+send 'ee9e54a316ced1374a13ca2e00000001'
+pause 1
+
+;PT
+send 'b4786d6bda2dd17690f5b0df362f539c54e7e1cd2cd0ac1f0acfaa51d673095729f88db1b6dd54be0b62d349e56557aa4e4980'
+pause 1
+send 13
+pause 1
+
+;AAD
+send '396d0892aff3212995e8f564083a0972'
+pause 1
+send 13
+pause 1
+
+;Disable DMA
+send '0'
+pause 5
+
+;Press any key to continue
+send '6'
+
+; -----------------------------------------------------------------------------
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_aes_cmac_256.ttl b/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_aes_cmac_256.ttl
new file mode 100644
index 0000000..b1f01df
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_aes_cmac_256.ttl
@@ -0,0 +1,47 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+changedir '.'
+logopen "MAC_hmac_aes_cmac_256.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto MAC service'
+
+setsync 1
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 1
+; INPUT
+; Key = f70b8a4eee3518bba071af55f25f7b698a5b7dc8865cdaca6d1c7993657acc95
+; Msg = 795ee1af7504621aac329f5081912de545fa11174f3979b14f11aa30df813a235b467fd8f3a14734fe5ac9e39105dcb25184673885cd19bc70ee5a53dd4e8149
+; OUTPUT
+; Mac = 93542734d6cd43de
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+send '3'
+pause 2
+
+;key
+send 'f70b8a4eee3518bba071af55f25f7b69'
+send '8a5b7dc8865cdaca6d1c7993657acc95'
+pause 1
+
+;Msg
+send '795ee1af7504621aac329f5081912de545fa11174f39'
+send '79b14f11aa30df813a235b467fd8f3a14734fe5ac9e3'
+send '9105dcb25184673885cd19bc70ee5a53dd4e8149'
+pause 1
+send 13
+pause 1
+
+;press any key
+send '5'
+pause 1
+
+
+logclose
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_sha_256.ttl b/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_sha_256.ttl
new file mode 100644
index 0000000..0381201
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/scripts/MAC-hmac_sha_256.ttl
@@ -0,0 +1,93 @@
+; Tera Term Setting:
+; 1. Before running Tera Term Macro script, you should set language as English
+; and transmit delay in Serial port setup to 5msec/char and 5msec/line.
+; 2. By default, Tera Term log will be stored in Tera Term installation Directory.
+changedir '.'
+logopen "MAC_hmac_sha_256.log" 0 0 0 1
+
+settitle 'PolarFire User Crypto MAC HMAC SHA 256 service'
+
+setsync 1
+
+; Set baud rate to 115200
+setbaud 115200
+
+; local echo off
+setecho 0
+
+send 13
+
+; ----------------------------------------------------------------------------------------------------------------------------------------------------------
+; Test Case 1 - DMA disabled
+; INPUT
+; Input Date: "Sample message for keylen= '0') && (*src <= '9'))
+ {
+ *dest = (*src - '0');
+ }
+ else if((*src >= 'a') && (*src <= 'f'))
+ {
+ *dest = (*src - 'a') + 10u;
+ }
+ else if((*src >= 'A') && (*src <= 'F'))
+ {
+ *dest = (*src - 'A') + 10u;
+ }
+ else if(*src != 0x00u)
+ {
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid data.", sizeof("\r\n Invalid data."));
+ error_flag = 1u;
+ }
+ return error_flag;
+}
+
+/*==============================================================================
+ Validate the input hex value .
+ */
+uint8_t validate_input(uint8_t ascii_input)
+{
+ uint8_t valid_key = 0u;
+
+ if(((ascii_input >= 'A') && (ascii_input <= 'F')) || \
+ ((ascii_input >= 'a') && (ascii_input <= 'f')) || \
+ ((ascii_input >= '0') && (ascii_input <= '9')))
+ {
+ valid_key = 1u;
+ }
+ else
+ {
+ valid_key = 0u;
+ }
+ return valid_key;
+}
+
+const uint8_t hex_chars[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/*==============================================================================
+ Display content of buffer passed as parameter as hex values.
+ */
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+)
+{
+ uint32_t inc;
+ uint8_t byte = 0;
+
+ UART_send(&g_uart, (const uint8_t*)" ", sizeof(" "));
+ for(inc = 0; inc < byte_length; ++inc)
+ {
+ if((inc > 1u) &&(0u == (inc % 16u)))
+ {
+ UART_send(&g_uart, (const uint8_t*)"\r\n ", sizeof("\r\n "));
+ }
+
+ byte = in_buffer[inc];
+ UART_send(&g_uart, &hex_chars[((byte & 0xF0) >> 4) ], 1);
+ UART_send(&g_uart, &hex_chars[(byte & 0x0F)], 1);
+ }
+
+}
+
+/*==============================================================================
+ Function to read data from UART terminal and stored it.
+ */
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+)
+{
+ uint8_t complete = 0u;
+ uint8_t rx_buff[1];
+ uint8_t rx_size = 0u;
+ uint16_t count = 0u;
+ uint16_t ret_size = 0u;
+ uint8_t first = 0u;
+ uint16_t src_ind = 0u;
+ uint8_t prev = 0;
+ uint8_t curr = 0;
+ uint8_t temp = 0;
+ uint8_t next_byte = 0;
+ uint16_t read_data_size = 0;
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, msg, msg_size);
+
+ if(size != 1)
+ {
+ read_data_size = size * 2;
+ }
+ else
+ {
+ read_data_size = size;
+ }
+
+ /* Read the key size sent by user and store it. */
+ count = 0u;
+ while(!complete)
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0u)
+ {
+ /* Is it to terminate from the loop */
+ if(ENTER == rx_buff[0])
+ {
+ complete = 1u;
+ }
+ /* Is entered key valid */
+ else if(validate_input(rx_buff[0]) != 1u)
+ {
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Invalid input.",
+ sizeof("\r\n Invalid input."));
+ UART_send(&g_uart, msg, msg_size);
+ complete = 0u;
+ count = 0u;
+ first = 0u;
+ clear_variable(src_ptr, 4);
+ }
+ else
+ {
+ if(next_byte == 0)
+ {
+ convert_ascii_to_hex(&src_ptr[src_ind], &rx_buff[0]);
+ prev = src_ptr[src_ind];
+ next_byte = 1;
+ }
+ else
+ {
+ convert_ascii_to_hex(&curr, &rx_buff[0]);
+ temp = ((prev << 4) & 0xF0);
+ src_ptr[src_ind] = (temp | curr);
+ next_byte = 0;
+ src_ind++;
+ }
+
+
+ /* Switching to next line after every 8 bytes */
+ if(((count % 32u) == 0x00u) && (count > 0x00u) && (complete != 0x01u))
+ {
+ UART_send(&g_uart, (const uint8_t *)"\n\r", sizeof("\n\r"));
+ first = 0u;
+ }
+
+ if(first == 0u)
+ {
+ UART_send(&g_uart, (const uint8_t *)" ", sizeof(" "));
+ first++;
+ }
+ UART_send(&g_uart, rx_buff, sizeof(rx_buff));
+ count++;
+ if(read_data_size == count)
+ {
+ complete = 1u;
+ }
+ }
+ }
+ }
+
+ if((count%2) == 0)
+ {
+ ret_size = count/2;
+ }
+ else
+ {
+ if(size!=1)
+ {
+ temp = src_ptr[src_ind];
+ src_ptr[src_ind] = ((temp << 4) & 0xF0);
+
+ ret_size = (count/2)+1;
+ }
+ else
+ {
+ ret_size = 1;
+ }
+ }
+
+ return ret_size;
+}
+
+/*==============================================================================
+ Function to get the key from user.
+ */
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+)
+{
+ volatile uint8_t invalid_ip = 1u;
+ uint8_t dma_enable = 0;
+
+ const uint8_t invalid_ms[] = "\r\n Invalid input. ";
+
+ while(invalid_ip != 0)
+ {
+ /* Read the 16 bytes of input data from UART terminal. */
+ get_input_data(&dma_enable, 1, msg, msg_size);
+
+ if(dma_enable >= 2)
+ {
+ UART_send(&g_uart, invalid_ms, sizeof( invalid_ms));
+ }
+ else
+ {
+ invalid_ip = 0;
+ }
+ }
+
+ return dma_enable;
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/application/helper.h b/user-crypto/miv-rv32-message-authentication/src/application/helper.h
new file mode 100644
index 0000000..6c586a6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/application/helper.h
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file helper.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Helper function public API.
+ *
+ */
+#ifndef __HELPER_H_
+#define __HELPER_H_ 1
+
+/******************************************************************************
+ * Maximum buffer size.
+ *****************************************************************************/
+#define MAX_RX_DATA_SIZE 256
+#define MASTER_TX_BUFFER 10
+
+/*==============================================================================
+ Macro
+ */
+#define VALID 0U
+#define INVALID 1U
+#define ENTER 13U
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+extern UART_instance_t g_uart;
+
+uint16_t get_input_data
+(
+ uint8_t* location,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+void get_key
+(
+ uint8_t key_type,
+ uint8_t* location,
+ uint8_t size,
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+uint16_t get_data_from_uart
+(
+ uint8_t* src_ptr,
+ uint16_t size,
+ const uint8_t* msg,
+ uint16_t msg_size
+);
+uint8_t enable_dma
+(
+ const uint8_t* msg,
+ uint8_t msg_size
+);
+void display_output
+(
+ uint8_t* in_buffer,
+ uint32_t byte_length
+);
+#endif /* __HELPER_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/application/main.c b/user-crypto/miv-rv32-message-authentication/src/application/main.c
new file mode 100644
index 0000000..e787166
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/application/main.c
@@ -0,0 +1,522 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file main.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief This Example Project demonstrates the usage of PolarFire User Crypto
+ * services for message authentication and hashing.
+ *
+ */
+#include "hal/hal.h"
+#include "fpga_design_config/fpga_design_config.h"
+#include "drivers/fpga_ip/CoreUARTapb/core_uart_apb.h"
+#include
+#include
+#include "stdint.h"
+#include
+#include
+
+#include "helper.h"
+#include "cal/calpolicy.h"
+#include "cal/pk.h"
+#include "cal/pkx.h"
+#include "cal/pkxlib.h"
+#include "cal/calini.h"
+#include "cal/utils.h"
+#include "cal/hash.h"
+#include "cal/drbgf5200.h"
+#include "cal/drbg.h"
+#include "cal/nrbg.h"
+#include "cal/sym.h"
+#include "cal/shaf5200.h"
+#include "cal/calenum.h"
+#include "cal/mac.h"
+
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+
+uint32_t g_user_crypto_base_addr = 0x62000000UL;
+/******************************************************************************
+ * Instruction message.
+ *****************************************************************************/
+const uint8_t read_dma_enable_ip[] =
+"\r\n Enter 1 to perform Symmetric encryption with DMA or \r\n\
+ 0 to perform Symmetric encryption without DMA: \r\n";
+
+/*==============================================================================
+ Messages displayed over the UART.
+ */
+const uint8_t g_greeting_msg[] =
+"\r\n\r\n\
+******************************************************************************\r\n\
+************* PolarFire User Crypto Example Project **************************\r\n\
+******************************************************************************\r\n\
+ This example project demonstrates the use of the User Crypto Message \r\n\
+ authentication services and hash services. The following User Crypto service\r\n\
+ are demonstrated:\r\n\
+ 1 - Galois/Counter Mode, GCM Message Authentication.\r\n\
+ 2 - Message authentication code - HMAC-SHA-256.\r\n\
+ 3 - Message authentication code - AES-CMAC-256.\r\n\
+ 4 - SHA-256 service.\r\n";
+const uint8_t g_select_operation_msg[] =
+"\r\n\
+------------------------------------------------------------------------------\r\n\
+ Select the Cryptographic operation to perform:\r\n\
+ Press Key '1' to perform AES-GCM-256 encryption \r\n\
+ Press Key '2' to perform HMAC SHA 256 \r\n\
+ Press Key '3' to perform HMAC AES-CMAC-256 \r\n\
+ Press Key '4' to perform hash operation \r\n\
+------------------------------------------------------------------------------\r\n";
+static const uint8_t g_separator[] =
+"\r\n\
+------------------------------------------------------------------------------";
+
+/*==============================================================================
+ Global Variables.
+ */
+/* AES-128 encryption/decryption. */
+ uint8_t __attribute__ ((section (".crypto_data"))) g_iv[16];
+ uint8_t __attribute__ ((section (".crypto_data"))) g_plain_text[128];
+
+
+ uint8_t __attribute__ ((section (".crypto_data"))) g_key_256bit[32];
+ uint8_t __attribute__ ((section (".crypto_data"))) g_auth_data[128];
+ uint8_t __attribute__ ((section (".crypto_data"))) tag[32];
+
+
+ uint8_t __attribute__ ((section (".crypto_data"))) g_mac[32];
+ uint8_t __attribute__ ((section (".crypto_data"))) g_encrypted_text[128];
+
+
+ uint8_t __attribute__ ((section (".crypto_data"))) g_hash_msg[128] = {0x00};
+ uint8_t __attribute__ ((section (".crypto_data"))) g_hash_result[32];
+
+/* Helper function.*/
+static void clr_hmac_sha_var(void);
+static void clr_hmac_aes_cmac_var(void);
+static void clr_gcm_msg_auth_var(void);
+static void clear_sha256_var(void);
+
+/*==============================================================================
+ Hash operation using SHA-256
+ */
+void sha_256bit_hash()
+{
+ uint16_t count = 0u;
+ uint8_t status;
+ uint8_t use_dma = 0;
+
+ const uint8_t sha_msg[] =
+ "\r\n Enter message to perform hashing (max 128 Bytes): \r\n";
+
+ /* Clear input and output variables */
+ clear_sha256_var();
+
+ /* Get the input Text/Data from the user and store it for Hashing. */
+ count = get_input_data(&g_hash_msg[0],sizeof(g_hash_msg), sha_msg,
+ sizeof(sha_msg));
+
+ /* Use dma or not */
+ use_dma = enable_dma(read_dma_enable_ip, sizeof(read_dma_enable_ip));
+
+ if(use_dma != 1)
+ {
+ /* Without DMA */
+ status = CALHash(SATHASHTYPE_SHA256, g_hash_msg, count, g_hash_result);
+ }
+ else
+ {
+ /* With DMA */
+ status = CALHashDMA(SATHASHTYPE_SHA256, g_hash_msg, count, g_hash_result,
+ X52CCR_DEFAULT);
+ }
+
+ if(SATR_SUCCESS == status)
+ {
+ if(use_dma == 1)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ }
+ /* Display the calculated Hash value */
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Calculated hash value for the input data:\r\n",
+ sizeof("\r\n Calculated hash value for the input data:\r\n"));
+ display_output(g_hash_result, sizeof(g_hash_result));
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ /* Display the error information */
+ UART_send(&g_uart, (const uint8_t *)"\r\n SHA-256 service fail\r\n",
+ sizeof("\r\n SHA-256 service fail\r\n"));
+ }
+}
+
+/*==============================================================================
+ Message authentication code - AES-CMAC-256
+ */
+static void hmac_aes_cmac_256(void)
+{
+ uint8_t status = 0u;
+ uint16_t msg_len = 0;
+
+ const uint8_t read_key_msg[] =
+ "\r\n Enter the 256-bit/32-byte key: \r\n";
+ const uint8_t read_data_msg[] =
+ "\r\n Enter the input data (max 128 bytes):\r\n";
+
+ /* Clear all global variable. */
+ clr_hmac_aes_cmac_var();
+
+ /* Get key. key size 256 bit*/
+ get_input_data(&g_key_256bit[0], sizeof(g_key_256bit), read_key_msg, sizeof(read_key_msg));
+
+ /* Read the 128 bytes of input data from UART terminal. */
+ msg_len = get_input_data(&g_plain_text[0], sizeof(g_plain_text), read_data_msg, sizeof(read_data_msg));
+
+ /* Without DMA */
+ status = CALMAC(SATMACTYPE_AESCMAC256,(uint32_t*)&g_key_256bit, sizeof(g_key_256bit),
+ g_plain_text, msg_len, g_mac);
+
+ /* Display the encrypted data in hex format. */
+ if(SATR_SUCCESS == status)
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Message Authentication successful \r\n Generated MAC:\r\n",
+ sizeof("\r\n Message Authentication successful \r\n Generated MAC:\r\n"));
+ display_output(g_mac, 8);
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Message Authentication fail\r\n",
+ sizeof("\r\n Message Authentication fail\r\n"));
+ }
+}
+
+/*==============================================================================
+ Message authentication code - HMAC-SHA-256
+ */
+static void hmac_sha_256(void)
+{
+ uint8_t status = 0u;
+ uint16_t msg_len = 0;
+ uint8_t use_dma = 0;
+
+ const uint8_t read_key_msg[] =
+ "\r\n Enter the 256 bit key to be used: \r\n";
+ const uint8_t read_data_msg[] =
+ "\r\n Enter input data(max 128 Bytes):\r\n";
+ const uint8_t read_dma_enable_ip[] =
+ "\r\n Enter 1 to perform Symmetric encryption with DMA or \r\n\
+ 0 to perform Symmetric encryption without DMA: \r\n";
+
+ /* Clear Global variables. */
+ clr_hmac_sha_var();
+
+ /* Get key. key size 256 bit*/
+ get_input_data(&g_key_256bit[0], sizeof(g_key_256bit), read_key_msg,
+ sizeof(read_key_msg));
+
+ /* Read the 32 bytes of input data from UART terminal. */
+ msg_len = get_input_data(&g_plain_text[0],sizeof(g_plain_text),
+ read_data_msg, sizeof(read_data_msg));
+
+ /* Use dma or not */
+ use_dma = enable_dma(read_dma_enable_ip, sizeof(read_dma_enable_ip));
+
+ if(use_dma != 1)
+ {
+ /* Without DMA */
+ status = CALMAC(SATMACTYPE_SHA256, (uint32_t*)&g_key_256bit, sizeof(g_key_256bit),
+ g_plain_text, msg_len, g_encrypted_text);
+ }
+ else
+ {
+ /* With DMA */
+ status = CALMACDMA(SATMACTYPE_SHA256, (uint32_t*)&g_key_256bit, sizeof(g_key_256bit),
+ g_plain_text, msg_len, g_encrypted_text, X52CCR_DEFAULT);
+ }
+
+ /* Display the encrypted data in hex format. */
+ if(SATR_SUCCESS == status)
+ {
+ if(use_dma == 1)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ }
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart,
+ (const uint8_t *)"\r\n Message Authentication successful \r\n Output data:\r\n",
+ sizeof("\r\n Message Authentication successful \r\n Output data:\r\n"));
+ display_output(g_encrypted_text, 32u);
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Error\r\n", sizeof("\r\n Error\r\n"));
+ }
+}
+
+/*==============================================================================
+ GCM Message Authentication - AES-GCM-256
+ */
+
+static void gcm_msg_auth(void)
+{
+ uint8_t status = 0u;
+ uint8_t use_dma = 0;
+ uint16_t msg_len = 0;
+ uint16_t aad_len = 0;
+ uint32_t g_tag_len = 0;
+
+ const uint8_t read_dma_enable_ip[] =
+ "\r\n Enter 1 to perform Symmetric encryption with DMA or \r\n\
+ 0 to perform Symmetric encryption without DMA: \r\n";
+ const uint8_t read_key_msg[] =
+ "\r\n Enter the 256-bit/32-byte key: \r\n";
+ const uint8_t read_data_msg[] =
+ "\r\n Enter the input data to encrypt(PT) (max: 128 Bytes):\r\n";
+ const uint8_t read_iv_msg[] =
+ "\r\n Enter the 16 bytes(128 bit) initialization vector(IV): \r\n";
+ const uint8_t read_auth_data_msg[] =
+ "\r\n Enter the 16 bytes of authentication data(AAD): \r\n";
+
+ /* Clear all global variable related to AES GCM */
+ clr_gcm_msg_auth_var();
+
+ /* Get key used for encryption. key size 256 bit*/
+ get_input_data(&g_key_256bit[0], sizeof(g_key_256bit), read_key_msg,
+ sizeof(read_key_msg));
+
+ /* Get the Initialization Vector value. IV size is 128 bit */
+ get_input_data(g_iv, sizeof(g_iv), read_iv_msg, sizeof(read_iv_msg));
+
+ /* Get the data to be encrypted. Data size is 16 bytes*/
+ msg_len = get_input_data(&g_plain_text[0], sizeof(g_plain_text),
+ read_data_msg, sizeof(read_data_msg));
+
+ /* Get additional authentication data (AAD). AAD size is 16 bytes*/
+ aad_len = get_input_data(&g_auth_data[0], sizeof(g_auth_data), read_auth_data_msg,
+ sizeof(read_auth_data_msg));
+
+ /* Use dma or not */
+ use_dma = enable_dma(read_dma_enable_ip, sizeof(read_dma_enable_ip));
+
+ if(use_dma != 1)
+ {
+ /* Without DMA */
+ status = CALSymEncAuth(SATSYMTYPE_AES256, (uint32_t*)&g_key_256bit[0],
+ SATSYMMODE_GCM, g_iv, g_plain_text,
+ g_encrypted_text, msg_len, g_auth_data, aad_len,
+ tag, 12);
+ }
+ else
+ {
+ /* With DMA */
+ status = CALSymEncAuthDMA(SATSYMTYPE_AES256, (uint32_t*)&g_key_256bit[0],
+ SATSYMMODE_GCM, g_iv, g_plain_text,
+ g_encrypted_text, msg_len, g_auth_data,
+ aad_len, tag, 12, X52CCR_DEFAULT);
+ }
+
+ /* Display the encrypted data in hex format. */
+ if(SATR_SUCCESS == status)
+ {
+ CALPKTrfRes(SAT_TRUE);
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Encrypted data(CT):\r\n",
+ sizeof("\r\n Encrypted data(CT):\r\n"));
+ display_output(g_encrypted_text, sizeof(g_encrypted_text)/2);
+ UART_send(&g_uart, (const uint8_t *)"\r\n\n Message Authentication Code(Tag):\r\n",
+ sizeof("\r\n\n Message Authentication Code(Tag):\r\n"));
+ display_output(tag, sizeof(tag));
+ }
+ else
+ {
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Error\r\n", sizeof("\r\n Error\r\n"));
+ }
+ /* GCM verification */
+
+ /* clear the plaintext buffer */
+ uint16_t bc ;
+ for(bc = 0 ; bc < sizeof(g_plain_text) ; bc++)
+ {
+ g_plain_text[bc] = 0 ;
+ }
+
+ status = CALSymDecVerify(SATSYMTYPE_AES256, (uint32_t*)&g_key_256bit[0], SATSYMMODE_GCM, g_iv
+ , g_encrypted_text, g_plain_text, msg_len, g_auth_data, aad_len, tag, 12);
+ if(SATR_SUCCESS == status)
+ {
+ status = CALSymTrfRes(SAT_TRUE);
+ if(SATR_SUCCESS == status)
+ {
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t *)"\r\n Decrypted data(CT):\r\n",
+ sizeof("\r\n Decrypted data(CT):\r\n"));
+ display_output(g_plain_text, sizeof(g_plain_text)/2);
+ UART_send(&g_uart, (const uint8_t *)"\r\n\n Message Authentication successful(Tag):\r\n",
+ sizeof("\r\n\n Message Authentication successful(Tag):\r\n"));
+ display_output(tag, sizeof(tag));
+ }
+ }
+
+}
+/*==============================================================================
+ Display greeting message when application is started.
+ */
+static void display_greeting(void)
+{
+ UART_send(&g_uart, g_greeting_msg,sizeof(g_greeting_msg));
+}
+
+/*==============================================================================
+ Display the choice of cryptographic operation to perform.
+ */
+static void display_operation_choices(void)
+{
+ UART_send(&g_uart, g_select_operation_msg, sizeof(g_select_operation_msg));
+}
+
+/*==============================================================================
+ Display the Option to continue or exit.
+ */
+static void display_option(void)
+{
+ uint8_t rx_size;
+ uint8_t rx_buff[1];
+
+ UART_send(&g_uart, g_separator, sizeof(g_separator));
+ UART_send(&g_uart, (const uint8_t*)"\r\n Press any key to continue.\r\n",
+ sizeof("\r\n Press any key to continue.\r\n"));
+ do
+ {
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ } while(0u == rx_size);
+}
+
+/******************************************************************************
+ * main function.
+ *****************************************************************************/
+int main( void )
+{
+ uint8_t rx_buff[1];
+ size_t rx_size = 0;
+
+
+ /* 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));
+
+ /* Initializes the Athena Processor. */
+ CALIni();
+
+ /* Display greeting message. */
+ display_greeting();
+
+ /* Select cryptographic operation to perform */
+ display_operation_choices();
+
+ for(;;)
+ {
+ /* Read input from UART terminal. */
+ rx_size = UART_get_rx(&g_uart, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ switch(rx_buff[0])
+ {
+ case '1':
+ /* Galois/Counter Mode, GCM Message Authentication */
+ gcm_msg_auth();
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '2':
+ /* Perform HMAC SHA 256 */
+ hmac_sha_256();
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '3':
+ /* Perform HMAC AES-CMAC-256 */
+ hmac_aes_cmac_256();
+ display_option();
+ display_operation_choices();
+ break;
+
+ case '4':
+ /* Perform SHA-256*/
+ sha_256bit_hash();
+ display_option();
+ display_operation_choices();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+static void clr_hmac_sha_var(void)
+{
+ uint16_t var = 0;
+
+ for(var = 0; var < sizeof(g_key_256bit); var++)
+ {
+ g_key_256bit[var] = 0;
+ }
+ for(var = 0; var < sizeof(g_plain_text); var++)
+ {
+ g_plain_text[var] = 0;
+ }
+}
+
+static void clr_gcm_msg_auth_var(void)
+{
+ uint16_t index = 0;
+
+ clr_hmac_sha_var();
+
+ for(index = 0; index < sizeof(g_iv); index++)
+ {
+ g_iv[index] = 0;
+ }
+ for(index = 0; index < sizeof(g_auth_data); index++)
+ {
+ g_auth_data[index] = 0;
+ }
+}
+
+static void clr_hmac_aes_cmac_var(void)
+{
+ uint16_t var = 0;
+
+ clr_hmac_sha_var();
+
+ for(var = 0; var < sizeof(g_mac); var++)
+ {
+ g_mac[var] = 0;
+ }
+}
+
+static void clear_sha256_var(void)
+{
+ volatile uint32_t index;
+
+ for(index = 0u; index < sizeof(g_hash_msg); index++)
+ {
+ g_hash_msg[index] = 0u;
+ }
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h b/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
new file mode 100644
index 0000000..3fd1438
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/fpga_design_config/fpga_design_config.h
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file 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 83000000UL
+#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 COREUARTAPB0_BASE_ADDR 0x70000000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70001000UL
+#define CORESPI_BASE_ADDR 0x70002000UL
+#define CORESYS_SERV_BASE_ADDR 0x70003000UL
+
+/***************************************************************************//**
+ * 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_ */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld b/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
new file mode 100644
index 0000000..8541db6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/boards/polarfire-eval-kit/platform_config/linker/miv-rv32-ram.ld
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 64k
+ crypto_ram (rw) : ORIGIN = 0x61000000, LENGTH = 32k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+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
+
+ . = 0x61000000;
+ .crypto_data : ALIGN(0x10)
+ {
+ . = ALIGN(0x10);
+ *(.crypto_data)
+ } > crypto_ram
+}
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/aesf5200.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/aesf5200.h
new file mode 100644
index 0000000..889dddd
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/aesf5200.h
@@ -0,0 +1,104 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 AES function hardware implementation for
+ CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef AESF5200_H
+#define AESF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef AESF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR aesf5200aes (SATSYMTYPE eSymType, SATSYMMODE eMode,
+ void *pIV, SATBOOL bLoadIV, const void *pSrc, void *pDest, SATUINT32_t uiLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200aesk (SATSYMTYPE eSymType, const SATUINT32_t *puiKey);
+
+extern SATR aesf5200gcm (SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen,
+ const void *pAuth, SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen,
+ SATBOOL bDecrypt);
+
+extern SATR aesf5200gcmdma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ const void *pSrc, void *pDest, SATUINT32_t uiEncLen, const void *pAuth,
+ SATUINT32_t uiAuthLen, void *pMAC, SATUINT32_t uiMACLen, SATBOOL bDecrypt,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR aesf5200kw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR aesf5200kr(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKrf, SATBOOL bDecrypt);
+
+extern SATR aesf5200dma(SATSYMTYPE eSymType, SATSYMMODE eMode, void *pIV,
+ SATBOOL bLoadIV, const void *pExtSrc, void *pExtDest, SATUINT32_t uiLen,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+extern SATR aesf5200krdma(SATSYMTYPE eSymType, SATSYMMODE eMode,
+ const SATUINT32_t *puiKey, void *pIV, SATBOOL bLoadIV, const void *pExtSrc,
+ void *pExtDest, SATUINT32_t uiLen, SATUINT32_t uiKrf,
+ SATUINT32_t uiDMAChConfig, SATBOOL bDecrypt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calcontext.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calcontext.h
new file mode 100644
index 0000000..fc408c2
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calcontext.h
@@ -0,0 +1,88 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL context management functions.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONTEXT_H
+#define CALCONTEXT_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Function resource handle. */
+/* ----- ------ ------- ---- */
+#define SATRES_DEFAULT (SATRESHANDLE)0U
+#define SATRES_CALSW (SATRESHANDLE)1U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+typedef struct{
+ SATUINT32_t uiBase;
+ SATRESCONTEXTPTR pContext;
+ }SATRESHANDLESTRUCT;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALCONTEXT_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATRESCONTEXTPTR CALContextCurrent(const SATRESHANDLE hResource);
+
+extern SATR CALContextLoad(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext);
+
+extern SATR CALContextRemove(const SATRESHANDLE hResource);
+
+extern SATR CALContextUnload(const SATRESHANDLE hResource);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void init_reshandles(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calenum.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calenum.h
new file mode 100644
index 0000000..6281f3f
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calenum.h
@@ -0,0 +1,289 @@
+/* -------------------------------------------------------------------
+ $Rev: 1566 $ $Date: 2018-09-14 11:04:30 -0400 (Fri, 14 Sep 2018) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALENUM_H
+#define CALENUM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* CAL base types. */
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+/* NULL definitions. */
+#define SAT_NULL 0
+
+/* Boolean definitions. */
+#define SAT_TRUE ((SATBOOL)1)
+#define SAT_FALSE ((SATBOOL)0)
+
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+#define SATSSPTYPE_NULL (SATSSPTYPE)0
+#define SATSSPTYPE_SYMKEY (SATSSPTYPE)1
+#define SATSSPTYPE_ASYMKEY (SATSSPTYPE)2
+/* Special marker for end of list. */
+#define SATSSPTYPE_LAST (SATSSPTYPE)3
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+#define SATASYMTYPE_NULL (SATASYMTYPE)0U
+#define SATASYMTYPE_DSA_SIGN (SATASYMTYPE)1U
+#define SATASYMTYPE_DSA_VERIFY (SATASYMTYPE)2U
+#define SATASYMTYPE_RSA_ENCRYPT (SATASYMTYPE)3U
+#define SATASYMTYPE_RSA_DECRYPT (SATASYMTYPE)4U
+#define SATASYMTYPE_DH (SATASYMTYPE)5U
+#define SATASYMTYPE_ECDSA_SIGN (SATASYMTYPE)6U
+#define SATASYMTYPE_ECDSA_VERIFY (SATASYMTYPE)7U
+#define SATASYMTYPE_ECDH (SATASYMTYPE)8U
+#define SATASYMTYPE_RSA_SIGN (SATASYMTYPE)9U
+#define SATASYMTYPE_RSA_VERIFY (SATASYMTYPE)10U
+/* Special marker for end of list. */
+#define SATASYMTYPE_LAST (SATASYMTYPE)11U
+
+
+/* Encoding Types */
+/* -------- ----- */
+#define SATRSAENCTYPE_NULL (SATRSAENCTYPE)0U
+#define SATRSAENCTYPE_PKCS (SATRSAENCTYPE)1U
+#define SATRSAENCTYPE_ANSI (SATRSAENCTYPE)2U
+#define SATRSAENCTYPE_PSS (SATRSAENCTYPE)3U
+/* Special marker for end of list. */
+#define SATRSAENCTYPE_LAST (SATRSAENCTYPE)4U
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher Type. */
+#define SATSYMTYPE_NULL (SATSYMTYPE)0U
+#define SATSYMTYPE_AES128 (SATSYMTYPE)1U
+#define SATSYMTYPE_AES192 (SATSYMTYPE)2U
+#define SATSYMTYPE_AES256 (SATSYMTYPE)3U
+#define SATSYMTYPE_AESKS128 (SATSYMTYPE)4U
+#define SATSYMTYPE_AESKS192 (SATSYMTYPE)5U
+#define SATSYMTYPE_AESKS256 (SATSYMTYPE)6U
+/* Special marker for end of list. */
+#define SATSYMTYPE_LAST (SATSYMTYPE)7U
+
+/* Names for common cipher key lengths, in bits. */
+#define SATSYMKEYSIZE_AES128 (SATSYMKEYSIZE)128U
+#define SATSYMKEYSIZE_AES192 (SATSYMKEYSIZE)192U
+#define SATSYMKEYSIZE_AES256 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS128 (SATSYMKEYSIZE)256U
+#define SATSYMKEYSIZE_AESKS192 (SATSYMKEYSIZE)384U
+#define SATSYMKEYSIZE_AESKS256 (SATSYMKEYSIZE)512U
+
+/* Cipher Mode. */
+#define SATSYMMODE_NULL (SATSYMMODE)0U
+#define SATSYMMODE_ECB (SATSYMMODE)1U
+#define SATSYMMODE_CBC (SATSYMMODE)2U
+#define SATSYMMODE_CFB (SATSYMMODE)3U
+#define SATSYMMODE_OFB (SATSYMMODE)4U
+#define SATSYMMODE_CTR (SATSYMMODE)5U
+#define SATSYMMODE_GCM (SATSYMMODE)6U
+#define SATSYMMODE_GHASH (SATSYMMODE)8U
+/* Special marker for end of list. */
+#define SATSYMMODE_LAST (SATSYMMODE)9U
+
+
+/* Hashes */
+/* ------ */
+#define SATHASHTYPE_NULL (SATHASHTYPE)0U
+#define SATHASHTYPE_SHA1 (SATHASHTYPE)1U
+#define SATHASHTYPE_SHA224 (SATHASHTYPE)2U
+#define SATHASHTYPE_SHA256 (SATHASHTYPE)3U
+#define SATHASHTYPE_SHA384 (SATHASHTYPE)4U
+#define SATHASHTYPE_SHA512 (SATHASHTYPE)5U
+#define SATHASHTYPE_SHA512_224 (SATHASHTYPE)6U
+#define SATHASHTYPE_SHA512_256 (SATHASHTYPE)7U
+/* Special marker for end of list. */
+#define SATHASHTYPE_LAST (SATHASHTYPE)8U
+
+/* Hash sizes defined in bits */
+#define SATHASHSIZE_NULL (SATHASHSIZE)0U
+#define SATHASHSIZE_SHA1 (SATHASHSIZE)160U
+#define SATHASHSIZE_SHA224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA256 (SATHASHSIZE)256U
+#define SATHASHSIZE_SHA384 (SATHASHSIZE)384U
+#define SATHASHSIZE_SHA512 (SATHASHSIZE)512U
+#define SATHASHSIZE_SHA512_224 (SATHASHSIZE)224U
+#define SATHASHSIZE_SHA512_256 (SATHASHSIZE)256U
+
+#define SATHASHSIZE_HASH160 (SATHASHSIZE)160U
+#define SATHASHSIZE_HASH192 (SATHASHSIZE)192U
+#define SATHASHSIZE_HASH224 (SATHASHSIZE)224U
+#define SATHASHSIZE_HASH256 (SATHASHSIZE)256U
+#define SATHASHSIZE_HASH320 (SATHASHSIZE)320U
+#define SATHASHSIZE_HASH384 (SATHASHSIZE)384U
+#define SATHASHSIZE_HASH512 (SATHASHSIZE)512U
+#define SATHASHSIZE_HASH521 (SATHASHSIZE)521U
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* Message Authentication Types */
+#define SATMACTYPE_NULL (SATMACTYPE)0U
+#define SATMACTYPE_SHA1 (SATMACTYPE)1U
+#define SATMACTYPE_SHA224 (SATMACTYPE)2U
+#define SATMACTYPE_SHA256 (SATMACTYPE)3U
+#define SATMACTYPE_SHA384 (SATMACTYPE)4U
+#define SATMACTYPE_SHA512 (SATMACTYPE)5U
+#define SATMACTYPE_SHA512_224 (SATMACTYPE)6U
+#define SATMACTYPE_SHA512_256 (SATMACTYPE)7U
+#define SATMACTYPE_AESCMAC128 (SATMACTYPE)10U
+#define SATMACTYPE_AESCMAC192 (SATMACTYPE)11U
+#define SATMACTYPE_AESCMAC256 (SATMACTYPE)12U
+#define SATMACTYPE_AESGMAC (SATMACTYPE)13U
+/* Special marker for end of list. */
+#define SATMACTYPE_LAST (SATMACTYPE)14U
+
+
+/* Message Authentication Flags */
+#define SATMACFLAG_OP (SATMACTYPEFLAG)0U
+#define SATMACFLAG_FIRSTPASS (SATMACTYPEFLAG)1U
+#define SATMACFLAG_FINALPASS (SATMACTYPEFLAG)2U
+#define SATMACFLAG_IKEYFINAL (SATMACTYPEFLAG)4U
+#define SATMACFLAG_OKEYFINAL (SATMACTYPEFLAG)8U
+
+
+/* Non-deterministic Random Bit Generator */
+/* ------- -------------- ----- */
+
+/* NRBG register write enables */
+#define SATNRBGCONFIG_NONE 0x0
+#define SATNRBGCONFIG_RNG_CSR 0x1
+#define SATNRBGCONFIG_RNG_CNTLIM 0x2
+#define SATNRBGCONFIG_RNG_VOTIMER 0X4
+#define SATNRBGCONFIG_RNG_FMSK 0X8
+
+/* RNG_CSR access defines */
+#define SATNRBGCONFIG_CSR_RODIS 0x0
+#define SATNRBGCONFIG_CSR_ROEN 0x1
+#define SATNRBGCONFIG_CSR_ROFATAL 0x2
+#define SATNRBGCONFIG_CSR_ROFATALCLR 0X4
+
+/* RNG_FMSK mask values */
+#define SATNRBGCONFIG_FMSK_ROOSCF 0xFF
+#define SATNRBGCONFIG_FMSK_MONOBITF 0x10000
+#define SATNRBGCONFIG_FMSK_POKERF 0x20000
+#define SATNRBGCONFIG_FMSK_RUNSF 0x40000
+#define SATNRBGCONFIG_FMSK_LRUNSF 0x80000
+#define SATNRBGCONFIG_FMSK_F1401 0xF0000
+#define SATNRBGCONFIG_FMSK_REPCNTF 0x100000
+#define SATNRBGCONFIG_FMSK_APROPF 0x200000
+#define SATNRBGCONFIG_FMSK_SP800 0x300000
+
+/* RNG_ROHEALTH mask values */
+#define SATNRBGCONFIG_HLTH_ROOSCF 0x3FC0
+#define SATNRBGCONFIG_HLTH_APROPF 0x20
+#define SATNRBGCONFIG_HLTH_REPCNTF 0x10
+#define SATNRBGCONFIG_HLTH_LRUNSF 0x8
+#define SATNRBGCONFIG_HLTH_RUNSF 0x4
+#define SATNRBGCONFIG_HLTH_POKERF 0x2
+#define SATNRBGCONFIG_HLTH_MONOBITF 0x1
+
+
+/* Return Codes */
+/* ------ ----- */
+#define SATR_SUCCESS (SATR)0U
+#define SATR_FAIL (SATR)1U
+#define SATR_BADPARAM (SATR)2U
+#define SATR_VERIFYFAIL (SATR)3U
+#define SATR_KEYSFULL (SATR)4U
+#define SATR_BUSY (SATR)5U
+#define SATR_ROFATAL (SATR)6U
+#define SATR_PARITYFLUSH (SATR)7U
+#define SATR_SIGNFAIL (SATR)8U
+#define SATR_VALIDATEFAIL (SATR)9U
+#define SATR_PAF (SATR)10U
+#define SATR_VALPARMX (SATR)11U
+#define SATR_VALPARMY (SATR)12U
+#define SATR_VALPARMB (SATR)13U
+#define SATR_DCMPPARMX (SATR)14U
+#define SATR_DCMPPARMB (SATR)15U
+#define SATR_DCMPPARMP (SATR)16U
+#define SATR_SIGNPARMD (SATR)17U
+#define SATR_SIGNPARMK (SATR)18U
+#define SATR_VERPARMR (SATR)19U
+#define SATR_VERPARMS (SATR)20U
+#define SATR_MSBICV1 (SATR)21U
+#define SATR_MSBICV2 (SATR)22U
+#define SATR_PADLEN (SATR)23U
+#define SATR_LSB0PAD (SATR)24U
+#define SATR_BADLEN (SATR)25U
+#define SATR_BADHASHTYPE (SATR)26U
+#define SATR_BADTYPE (SATR)27U
+#define SATR_BADMODE (SATR)28U
+#define SATR_BADCONTEXT (SATR)29U
+#define SATR_BADHASHLEN (SATR)30U
+#define SATR_BADMACTYPE (SATR)31U
+#define SATR_BADMACLEN (SATR)32U
+#define SATR_BADHANDLE (SATR)33U
+#define SATR_FNP (SATR)34U
+#define SATR_HFAULT (SATR)35U
+#define SATR_NOPEND (SATR)36U
+#define SATR_BADRSAENC (SATR)37U
+#define SATR_BADMOD (SATR)38U
+/* Special marker for end of list. */
+#define SATR_LAST (SATR)39U
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* See caltypes.h for type definitions associated with defines above. */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALENUM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calini.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calini.h
new file mode 100644
index 0000000..62461d1
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calini.h
@@ -0,0 +1,69 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL initialization
+ ------------------------------------------------------------------- */
+
+#ifndef CALINI_H
+#define CALINI_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALINI_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALIni(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calpolicy.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calpolicy.h
new file mode 100644
index 0000000..2a43445
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/calpolicy.h
@@ -0,0 +1,183 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file defining CAL policy for endianess, HW/SW, etc.
+ ------------------------------------------------------------------- */
+
+#ifndef CALPOLICY_H
+#define CALPOLICY_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+
+/* The following include provides a custom configuration header file when
+ CALCONFIGH is defined
+*/
+#ifdef CALCONFIGH
+# include CALCONFIGH
+#else
+# error "CALCONFIGH not defined. CAL requires a custom configuration header \
+defined by CALCONFIGH. Review CAL README."
+#endif
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* Context switching */
+#ifndef MAXRESHANDLES
+# define MAXRESHANDLES 1
+#endif
+
+/* Little Endian (default) / Big Endian */
+#ifndef SAT_LITTLE_ENDIAN
+# define SAT_LITTLE_ENDIAN 1
+#endif
+
+/* PK SW Point Validate Checking */
+#ifndef PKSWCHKVALPT
+# define PKSWCHKVALPT 1
+#endif
+
+/* DMA */
+#ifndef USE_X52EXEC_DMA
+# define USE_X52EXEC_DMA 0
+#endif
+
+/* SHA */
+#define MAXHASHLEN 512
+#define MAXHMACKEYLEN 512
+
+/* RNG */
+#define NRBGSIMNUMRO 16
+#define ENTROPYMEMBLOCKS 7
+#define BUFMEMBLOCKS 3
+#ifndef RNXBLKLEN
+#define RNXBLKLEN 32
+#endif
+#ifndef RNXBLKOUTLEN
+#define RNXBLKOUTLEN 4
+#endif
+
+#ifndef USENRBGSW
+# define USENRBGSW 0
+#endif
+
+/* PK */
+#ifndef PKX0_BASE
+# define PKX0_BASE 0xE0000000u
+#endif
+
+#if USEPKSW
+# ifndef MAXMODSIZE
+# define MAXMODSIZE 8192
+# endif
+# ifndef PKSWBUFSIZE
+# define PKSWBUFSIZE 15*(MAXMODSIZE/32)
+# endif
+#else
+# define USEPKSW 0
+#endif
+
+/* Set default values for X52 configuration defines. */
+#ifndef X52_CFG_OPT
+# define X52_CFG_OPT 0
+#endif
+#ifndef X52_LIR_LEN
+# define X52_LIR_LEN 0x800
+#endif
+#ifndef X52_BER_LEN
+# define X52_BER_LEN 0x400
+#endif
+#ifndef X52_MMR_LEN
+# define X52_MMR_LEN 0x400
+#endif
+#ifndef X52_TSR_LEN
+# define X52_TSR_LEN 0x400
+#endif
+#ifndef X52_FPR_LEN
+# define X52_FPR_LEN 0x400
+#endif
+#if X52_LIR_ROM_LEN>0 && X52_LIR_LEN>X52_LIR_ROM_LEN
+# define PKX_OFFSET 2048
+#else
+# define PKX_OFFSET 0
+#endif
+
+/* X52 Configuration Options */
+#define AESPKX (X52_CFG_OPT&0x00000001u)
+#define AESPKXGCM (X52_CFG_OPT&0x00000008u)
+#define AESPKXFASTKEY (X52_CFG_OPT&0x01000000u)
+#define SHAPKXOPT1 (X52_CFG_OPT&0x00000020u)
+#define SHAPKXOPT224 (X52_CFG_OPT&0x00000040u)
+#define SHAPKXOPT256 (X52_CFG_OPT&0x00000080u)
+#define SHAPKXOPT384 (X52_CFG_OPT&0x00000100u)
+#define SHAPKXOPT512 (X52_CFG_OPT&0x00000200u)
+#define SHAPKXOPT5124 (X52_CFG_OPT&0x00400000u)
+#define SHAPKXOPT5126 (X52_CFG_OPT&0x00800000u)
+
+/* Define the maximum number of return values that may be handled using
+ CAL*TrfRes() function(s).
+*/
+#define CAL_MAXTRFS 4
+
+/* Volatile pointer operations */
+/* These access macros are designed so that they may be redefined by a
+ user compiling CAL.
+*/
+#ifndef CALREAD32
+# define CALREAD32(ptr) ( *(ptr) )
+#endif
+#ifndef CALWRITE32
+# define CALWRITE32(ptr, val) ( *(ptr)=val )
+#endif
+#ifndef CALPOLL32
+# define CALPOLL32(ptr, val, mask) while ((*(ptr) & (mask)) != (val));
+#endif
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+#ifndef CALPOLICY_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+/* NOTE: this header file does not have an associated C file. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/caltypes.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/caltypes.h
new file mode 100644
index 0000000..3b2fe0b
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/caltypes.h
@@ -0,0 +1,328 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ This file defines common types in the CAL.
+
+ Since support for the C99 stdint.h integer types is not universal,
+ these are defined herein and may require customization from compiler
+ to compiler, or use of the stdint.h header, if present (recommended).
+
+ C99 supports 64-bit types; however, support in older compilers is
+ spotty. For those that do not support it, the macro NO64BITINT may be
+ defined by the user to prevent defintion of 64-bit types. This is
+ generally safe with CAL-PK and CAL-SYM; however, this is incompatible
+ with CAL-SW.
+
+ Most CAL types and constants are defined with the "SAT" prefix to
+ reduce the chance of name space collisions with other users.
+ ------------------------------------------------------------------- */
+
+#ifndef CALTYPES_H
+#define CALTYPES_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* Base Types */
+/* ---- ----- */
+
+/* The user may compile using stdint.h instead of the definitions below
+ by defining the macro INC_STDINT_H. */
+#ifdef INC_STDINT_H
+#include
+#endif
+
+/* Integer type abstraction layer. */
+#ifndef INC_STDINT_H
+
+typedef unsigned char uint8_t;
+typedef signed char int8_t;
+
+typedef unsigned short uint16_t;
+typedef signed short int16_t;
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+
+/* stdint.h is a C99 feature, and C99 supports 64-bit ints, so this is
+ immune to the macro used to disable 64-bit int support.
+*/
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+
+typedef long uintptr_t;
+
+#endif
+
+/* Boolean type. */
+typedef uint8_t SATBOOL;
+
+/* Unsigned integer type */
+typedef uint8_t SATUINT8_t;
+typedef uint16_t SATUINT16_t;
+typedef uint32_t SATUINT32_t;
+#ifdef INC_STDINT_H
+typedef uint64_t SATUINT64_t;
+#else
+#ifndef NO64BITINT
+typedef uint64_t SATUINT64_t;
+#endif
+#endif
+
+/* Integer type */
+typedef int8_t SATINT8_t;
+typedef int16_t SATINT16_t;
+typedef int32_t SATINT32_t;
+#ifdef INC_STDINT_H
+typedef int64_t SATINT64_t;
+#else
+#ifndef NO64BITINT
+typedef int64_t SATINT64_t;
+#endif
+#endif
+
+typedef uintptr_t SATUINTPTR_t;
+
+/* Major cipher key/SSP type. */
+/* ----- ------ ------- ----- */
+typedef uint8_t SATSSPTYPE;
+typedef SATSSPTYPE * SATSSPTYPEPTR;
+
+
+/* Asymmetric Ciphers */
+/* ---------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATASYMTYPE;
+typedef SATASYMTYPE * SATASYMTYPEPTR;
+
+/* Cipher size type. */
+typedef uint16_t SATASYMSIZE;
+typedef SATASYMSIZE * SATASYMSIZEPTR;
+
+/* Cipher encoding */
+typedef uint8_t SATRSAENCTYPE;
+typedef SATRSAENCTYPE * SATRSAENCTYPEPTR;
+
+/* DSA public/private key. */
+typedef struct {
+ uint16_t ui16PLen; /* Length of modulus p. */
+ uint16_t ui16QLen; /* Length of prime divisor q. */
+ uint32_t *pui32P; /* Prime modulus p. */
+ uint32_t *pui32Q; /* Prime divisor q. */
+ uint32_t *pui32G; /* Generator g, length==p. */
+ uint32_t *pui32X; /* Private key x, length==p. */
+ uint32_t *pui32Y; /* Private key y, length==q. */
+} SATASYMDSADOMAIN;
+typedef SATASYMDSADOMAIN * SATASYMDSADOMAINPTR;
+
+
+/* Symmetric Ciphers */
+/* --------- ------- */
+
+/* Cipher type. */
+typedef uint8_t SATSYMTYPE;
+typedef SATSYMTYPE * SATSYMTYPEPTR;
+
+/* Cipher key size type (in bits). */
+typedef uint16_t SATSYMKEYSIZE;
+typedef SATSYMKEYSIZE * SATSYMKEYSIZEPTR;
+
+/* Cipher mode type. */
+typedef uint8_t SATSYMMODE;
+typedef SATSYMMODE * SATSYMMODEPTR;
+
+/* Cipher key object. */
+/* Other fields are only valid when sstCipher!=SATSYMTYPE_NULL. */
+typedef struct {
+ SATSYMTYPE sstCipher;
+ SATSYMKEYSIZE ssksKeyLen;
+ uint32_t *pui32Key;
+} SATSYMKEY;
+typedef SATSYMKEY * SATSYMKEYPTR;
+
+
+/* Hashes */
+/* ------ */
+
+/* Hash type. */
+typedef uint8_t SATHASHTYPE;
+typedef SATHASHTYPE * SATHASHTYPEPTR;
+
+/* Hash size type (in bits). */
+typedef uint16_t SATHASHSIZE;
+typedef SATHASHSIZE * SATHASHSIZEPTR;
+
+
+/* Context switching. */
+/* ----- ------ ------- ----- */
+
+typedef uint32_t SATRESHANDLE;
+typedef SATRESHANDLE * SATRESHANDLEPTR;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+} SHACTX;
+
+typedef struct {
+ SATHASHTYPE sshashtype;
+ uint32_t uiRunLen;
+ uint32_t uiKeyLen;
+ uint32_t uiHash[MAXHASHLEN/32]; /* holds intermed hash */
+ uint32_t uiKey[MAXHMACKEYLEN/32]; /* holds intermed key */
+} SHAHMACCTX;
+
+typedef struct {
+ uint8_t uiContextType;
+ union{
+ SHACTX ctxSHA;
+ SHAHMACCTX ctxMAC;
+ }CTXUNION;
+} SATRESCONTEXT;
+typedef SATRESCONTEXT * SATRESCONTEXTPTR;
+
+
+/* Message Authentication Codes */
+/* ------- -------------- ----- */
+
+/* MAC type. */
+typedef uint8_t SATMACTYPE;
+typedef SATMACTYPE * SATMACTYPEPTR;
+typedef uint8_t SATMACTYPEFLAG;
+
+
+/* Random Number Generator */
+/* ------ ------ --------- */
+typedef union {
+ uint32_t u32[4];
+ uint8_t u8[16];
+} uint128_t;
+
+typedef struct {
+ uint128_t ui128V;
+ uint128_t ui128K[2];
+ uint32_t uiReseedCnt;
+ uint32_t uiReseedLim;
+ uint32_t uiEntropyFactor;
+ SATSYMKEYSIZE eStrength;
+ SATBOOL bTesting;
+
+} DRBGCTX;
+
+typedef DRBGCTX * DRBGCTXPTR;
+
+
+/* Function Return Code */
+/* -------- ------ ---- */
+typedef uint16_t SATR ;
+typedef SATR * SATRPTR ;
+
+
+/* Transfer Results */
+/* -------- ------- */
+typedef struct {
+ SATUINT32_t uiLen;
+ volatile SATUINT32_t* vpuiSrc;
+ void* pDest;
+} SATDATATRF;
+
+typedef struct {
+ SATUINT32_t uiResType;
+ SATUINT32_t uiNumDataTrf;
+ SATDATATRF dtrfArray[CAL_MAXTRFS];
+} SATRESULT;
+
+
+/* EC Ultra Structs */
+/* -- ----- ------- */
+typedef uint32_t SATECTYPE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiX;
+ SATUINT32_t* puiY;
+} SATECPOINT;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiMod;
+ SATUINT32_t* puiMontPrecompute;
+ SATUINT32_t* puiRSqd;
+} SATECMONTMOD;
+
+typedef struct {
+ SATUINT32_t uiCurveSize;
+ SATECTYPE eCurveType;
+ SATECPOINT* pBasePoint;
+ SATECMONTMOD* pModP;
+ SATECMONTMOD* pModN;
+ SATUINT32_t* puiA;
+ SATUINT32_t* puiB;
+} SATECCURVE;
+
+typedef struct {
+ SATUINT32_t uiLen;
+ SATUINT32_t* puiSigR;
+ SATUINT32_t* puiSigS;
+ SATUINT32_t* puiSigX;
+ SATUINT32_t* puiSigY;
+} SATECDSASIG;
+
+typedef struct {
+ SATHASHSIZE sHashLen;
+ SATUINT32_t* puiHash;
+} SATHASH;
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef CALTYPES_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NOTE: this header file does not have an associated C file. */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/config_user.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/config_user.h
new file mode 100644
index 0000000..3728565
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/config_user.h
@@ -0,0 +1,44 @@
+/* -------------------------------------------------------------------
+ $Rev: 727 $ $Date: 2017-10-20 16:50:53 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+
+ User configuration file to include/exclude CAL components.
+ ------------------------------------------------------------------- */
+
+#ifndef CALCONFIG_F5200_H
+#define CALCONFIG_F5200_H
+
+#include "x52cfg_user.h"
+#include
+
+extern uint32_t g_user_crypto_base_addr;
+
+#define SAT_LITTLE_ENDIAN 1
+#define PKX0_BASE (g_user_crypto_base_addr)
+#define USEPKX 1
+#define USEAESPKX 1
+#define USESHAPKX 1
+#define USEDRBGPKX 1
+#define USENRBGPKX 1
+#define USECALCTX 1
+
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbg.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbg.h
new file mode 100644
index 0000000..dba16f7
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbg.h
@@ -0,0 +1,91 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for DRBG functions for CAL
+ ------------------------------------------------------------------- */
+
+#ifndef DRBG_H
+#define DRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define CALDRBGENTROPYFACTOR 2
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALDRBGInstantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr,
+ SATUINT32_t uiPzStrLen, SATSYMKEYSIZE eStrength,
+ SATUINT32_t uiEntropyFactor, SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR CALDRBGReseed(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen);
+
+extern SATR CALDRBGGenerate(const SATUINT32_t *puiAddIn, SATUINT32_t uiAddInLen,
+ SATBOOL bPredResist, SATUINT32_t *puiOut, SATUINT32_t uiOutBlocks);
+
+extern SATR CALDRBGUninstantiate(void);
+
+extern SATR CALDRBGGetCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGLoadCtx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR CALDRBGGetbInst(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+extern SATR CALDrbgTrfRes(SATBOOL bBlock);
+
+extern void CALDrbgIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbgf5200.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbgf5200.h
new file mode 100644
index 0000000..d7f6c4c
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/drbgf5200.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for F5200 DRBG function hardware implementations
+ in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef DRBGF5200_H
+#define DRBGF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+#define RNXEFACTOR (X52BER+2)
+#define RNXIRLEN (X52BER+2)
+#define RNXKEYORD (X52BER+3)
+#define RNXRESPRED (X52BER+4)
+#define RNXTESTSEL (X52BER+5)
+#define RNXBADDIN (X52BER+6)
+#define RNXPPSTR (X52BER+7)
+#define RNXPCTX (X52BER+8)
+#define RNXPRENT (X52BER+13)
+#define RNXITMP3 (X52BER+20)
+#define RNXPCTX2 (X52BER+22)
+/* These use same locs as tb generator, but can change */
+#define RNXRDATA (X52BER_ENDIAN+0x24)
+#define RNXAIDATAOFF 0x0062
+#define RNXAIDATA (X52BER_ENDIAN+RNXAIDATAOFF)
+#define RNXCTXOFF 0x0094
+#define RNXCTX (X52FPR+RNXCTXOFF)
+#define RNXCTXV (X52FPR_ENDIAN+RNXCTXOFF+6)
+#define RNXCTXVMMR (X52MMR_ENDIAN+RNXCTXOFF+6)
+#define RNXTESTENT (X52TSR_ENDIAN+8)
+
+#define RNXCTXWORDS 18
+#define RNXBLENLOC (RNXCTX+RNXCTXWORDS)
+#define RNXBOUTLENLOC (RNXCTX+RNXCTXWORDS+1)
+
+#define RNXMAXTESTENT32 512
+#define CALDRBGMAXADDINLEN X52_BER_LEN-RNXAIDATAOFF-4
+#define CALDRBGMAXPSNONCELEN X52_BER_LEN-RNXAIDATAOFF-4
+
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef DRBGF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR drbgf5200Ini(void);
+
+extern SATR drbgf5200TrfRes(SATBOOL bBlock);
+
+extern SATR drbgf5200instantiate(const SATUINT32_t *puiNonce,
+ SATUINT32_t uiNonceLen, const SATUINT32_t *puiPzStr, SATUINT32_t uiPzStrLen,
+ SATSYMKEYSIZE eStrength, SATUINT32_t uiEntropyFactor,
+ SATUINT32_t uiReseedLim, SATBOOL bTesting);
+
+extern SATR drbgf5200reseed(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen);
+
+extern SATR drbgf5200generate(const SATUINT32_t *puiAddIn,
+ SATUINT32_t uiAddInLen, SATBOOL bPredResist, SATUINT32_t uiReqLen,
+ SATUINT32_t *puiOut);
+
+extern SATR drbgf5200uninstantiate(void);
+
+extern SATR drbgf5200getctx(DRBGCTXPTR drbgCtxExt);
+
+extern SATR drbgf5200loadctx(DRBGCTXPTR drbgCtxExt);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/hash.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/hash.h
new file mode 100644
index 0000000..f3fd6d4
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/hash.h
@@ -0,0 +1,102 @@
+/* -------------------------------------------------------------------
+ $Rev: 1293 $ $Date: 2017-07-27 14:09:14 -0400 (Thu, 27 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL hash functions.
+ ------------------------------------------------------------------- */
+
+#ifndef HASH_H
+#define HASH_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+extern const SATHASHSIZE uiHashWordLen[SATHASHTYPE_LAST];
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef HASH_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALHash(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash);
+
+extern SATR CALHashDMA(SATHASHTYPE eHashType, const void *pMsg,
+ SATUINT32_t uiMsgLen, void *pHash, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALHashCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATBOOL bFinal);
+
+extern SATR CALHashCtxIni(const SATRESCONTEXTPTR pContext,
+ const SATHASHTYPE eHashType);
+
+extern SATR CALHashIni(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR CALHashWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALHashRead(void *pHash);
+
+extern SATR CALKeyTree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetHashLen(SATHASHTYPE eHashType);
+
+extern SATUINT32_t iGetBlockLen(SATHASHTYPE eHashType);
+
+extern SATR CALHashCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetRunLen(SATRESCONTEXTPTR const pContext);
+
+extern SATR CALHashTypeIni(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/mac.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/mac.h
new file mode 100644
index 0000000..acdc767
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/mac.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL MAC functions.
+ ------------------------------------------------------------------- */
+
+#ifndef MAC_H
+#define MAC_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef MAC_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALMAC(SATMACTYPE eMACType, const SATUINT32_t *pKey, SATUINT32_t uiKeyLen,
+ const void *pMsg, SATUINT32_t uiMsgLen, void *pMAC);
+
+extern SATR CALMACDMA(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALMACIni(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, SATUINT32_t uiMsgLen);
+
+extern SATR CALMACCtx(const SATRESHANDLE hResource,
+ const SATRESCONTEXTPTR pContext, const void *pMsg, SATUINT32_t uiMsgLen,
+ void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR CALMACCtxIni(const SATRESCONTEXTPTR pContext, const SATHASHTYPE eHashType,
+ const SATUINT32_t *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR CALMACWrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR CALMACRead(void *pMAC);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t iGetMACKeyLen(SATMACTYPE eMACType);
+
+extern SATR CALMACCtxLoad(const SATRESHANDLE hResource,
+ SATRESCONTEXTPTR const pContext, SATUINT32_t uiRunLen);
+
+extern SATUINT32_t iGetMACRunLen(SATRESCONTEXTPTR const pContext);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32i-user-crypto-lib.a b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32i-user-crypto-lib.a
new file mode 100644
index 0000000..5fda638
Binary files /dev/null and b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32i-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32imc-user-crypto-lib.a b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32imc-user-crypto-lib.a
new file mode 100644
index 0000000..ee7bcf4
Binary files /dev/null and b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/miv-rv32imc-user-crypto-lib.a differ
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/nrbg.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/nrbg.h
new file mode 100644
index 0000000..d517065
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/nrbg.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for NRBG functions for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef NRBG_H
+#define NRBG_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef NRBG_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALNRBGSetTestEntropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+extern SATR CALNRBGGetEntropy(SATUINT32_t * puiEntropy, SATUINT32_t uiEntLen32,
+ SATBOOL bTesting);
+
+extern SATR CALNRBGConfig(SATUINT32_t uiWriteEn, SATUINT32_t uiCSR,
+ SATUINT32_t uiCntLim, SATUINT32_t uiVoTimer, SATUINT32_t uiFMsk,
+ SATUINT32_t* puiStatus);
+
+extern SATUINT32_t CALNRBGHealthStatus(void);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATUINT32_t CALNRBGGetTestEntLen(void);
+
+extern SATR nrbgpkxgetentropy(SATUINT32_t * puiEntropy,
+ SATUINT32_t uiEntLen32);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pk.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pk.h
new file mode 100644
index 0000000..5983d9a
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pk.h
@@ -0,0 +1,302 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PK_H
+#define PK_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef PK_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALPKTrfRes(SATBOOL bBlock);
+
+extern SATR CALDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiX, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiN,
+ SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiY, const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiG, const SATUINT32_t* puiY,
+ const SATUINT32_t* puiR, const SATUINT32_t* puiS, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALECDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALECDSASignHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignHashCM(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSASignTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerify(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,const
+ SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyTwist(const SATUINT32_t* puiHash, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALECDSAVerifyHash(const SATUINT32_t* puiMsg, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECDSAVerifyTwistHash(const SATUINT32_t* puiMsg,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwist(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod,const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALECPtValidate(const SATUINT32_t* puiPx, const SATUINT32_t* puiPy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen);
+
+extern SATR CALECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALExpoCM(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALRSACRT(const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t * puiE, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiQ, const SATUINT32_t * puiN,
+ const SATUINT32_t * puiNMu, SATUINT32_t uiLen, SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig);
+
+extern SATR CALRSACRTSignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSACRTSignHashCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALRSASignHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATBOOL bDMA, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiSig);
+
+extern SATR CALRSAVerifyHash(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiMsg, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiSig, SATBOOL bDMA,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPurge52(SATBOOL bVerify);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkx.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkx.h
new file mode 100644
index 0000000..c23dda4
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkx.h
@@ -0,0 +1,409 @@
+/* -------------------------------------------------------------------
+ $Rev: 1298 $ $Date: 2017-08-04 13:04:19 -0400 (Fri, 04 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for for CAL PK.
+ ------------------------------------------------------------------- */
+
+#ifndef PKX_H
+#define PKX_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* X5200 Addressing */
+#define X52BER ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52LIR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00004000u))
+#define X52CSR ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F80u))
+#define X52CSRMERRS ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F8Cu))
+#define X52CSRMERRT0 ((volatile SATUINT32_t *) (PKX0_BASE + 0x00007F94u))
+
+#if SAT_LITTLE_ENDIAN
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00008000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00009000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000A000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x0000B000u))
+#define X52DMACONFIG_ENDIAN 0x8
+#else
+#define X52BER_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00000000u))
+#define X52MMR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00001000u))
+#define X52TSR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00002000u))
+#define X52FPR_ENDIAN ((volatile SATUINT32_t *) (PKX0_BASE + 0x00003000u))
+#define X52DMACONFIG_ENDIAN 0x0
+#endif
+
+/* X5200 Macros */
+#define X52GO(x) (0x10 | ((x)<<8))
+
+/* Counter Measures */
+#define RANDLEN 4
+
+/* X5200 CSRMAIN bit field masks. */
+#define X52CSRMAINRST 1
+#define X52CSRMAINCCMPLT 2
+#define X52CSRMAINCMPLT 4
+#define X52CSRMAINBUSY 8
+#define X52CSRMAINGO 0x10
+#define X52CSRMAINPURGE 0x20
+#define X52CSRMAINECDIS 0x40
+#define X52CSRMAINALARM 0x80
+#define X52CSRMAINLIRA ((0xFFF) << 8)
+#define X52CSRMERRSSEC ((0x2) << 24)
+#define X52CSRMERRSA 0x1FFF
+
+/* Address pointers for ROM'd P-curve moduli */
+#define P192_MOD (&uiROMMods[0])
+#define P224_MOD (&uiROMMods[1])
+#define P256_MOD (&uiROMMods[2])
+#define P384_MOD (&uiROMMods[3])
+#define P521_MOD (&uiROMMods[4])
+
+/* X5200 Addressing Flags */
+#define X52BYTEREVERSE_FLAG 1
+#define X52WORDREVERSE_FLAG 2
+#define X52BYTEREVERSE 0x00002000
+#define X52WORDREVERSE 0x00004000
+#define X52ADDRESSRANGE 0x2000
+
+/* X5200 DMA channel configuration constants. */
+#define X52CCR_DEFAULT 0 /* BSIZE=auto, ESWP=none, PROT=user, INC=inc */
+#define X52CCR_BSIZEAUTO 0 /* BSIZE=auto */
+#define X52CCR_BSIZEBYTE 0x10 /* BSIZE=byte */
+#define X52CCR_BSIZEHWORD 0x20 /* BSIZE=half word */
+#define X52CCR_BSIZEWORD 0x30 /* BSIZE=word */
+#define X52CCR_ESWPNONE 0 /* ESWP=none */
+#define X52CCR_ESWPWORD 0x8 /* ESWP=swap bytes in word [0123]->[3210] */
+#define X52CCR_PROTUSER 0 /* PROT=user */
+#define X52CCR_PROTPRIV 0x2 /* PROT=priv */
+#define X52CCR_INCADDR 0 /* INC=inc */
+#define X52CCR_NOINCADDR 0x1 /* INC=non-inc */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef PKX_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALPKXIni(void);
+
+extern void CALPKMem32Load(volatile SATUINT32_t * puiDst,
+ const SATUINT32_t * puiSrc, SATUINT32_t uiNum );
+
+extern SATR CALPKXTrfRes(SATBOOL bBlock);
+
+extern SATR CALPKXPreCompute(const SATUINT32_t* puiMod, SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen);
+
+extern SATR CALPKXExpo(const SATUINT32_t* puiBase, const SATUINT32_t* puiExpo,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiExpLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXExpoCM(const SATUINT32_t* puiBase,
+ const SATUINT32_t* puiExpo, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiExpLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXDSASign(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASignCM(const SATUINT32_t* puiHash, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiG,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiX, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig, const SATBOOL bCM);
+
+extern SATR CALPKXDSAVerify(const SATUINT32_t *puiHash,
+ const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu,
+ const SATUINT32_t *puiQ, const SATUINT32_t *puiQMu,
+ SATUINT32_t uiN, SATUINT32_t uiL);
+
+extern SATR CALPKXDSAVHDMA(const SATUINT32_t *puiExtInput, SATHASHTYPE eHashType,
+ SATUINT32_t uiMsgLen, const SATUINT32_t *puiG, const SATUINT32_t *puiY,
+ const SATUINT32_t *puiSigR, const SATUINT32_t *puiSigS,
+ const SATUINT32_t *puiP, const SATUINT32_t *puiPMu, const SATUINT32_t *puiQ,
+ const SATUINT32_t *puiQMu, SATUINT32_t uiN, SATUINT32_t uiL,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXModRed(const SATUINT32_t* puiA, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiALen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMult(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiMod, const SATUINT32_t* puiMu, SATUINT32_t uiModLen,
+ SATUINT32_t* puiResult);
+
+extern SATR CALPKXMMultAdd(const SATUINT32_t* puiA, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiC, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiModLen, SATUINT32_t* puiResult);
+
+extern SATR CALPKXECMult(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwist(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx,const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultCM(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t * puiN, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultTwistCM(const SATUINT32_t* puiMul,
+ const SATUINT32_t* puiPx, const SATUINT32_t* puiPy, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t * puiN, SATUINT32_t uiLen, SATUINT32_t* puiRx,
+ SATUINT32_t* puiRy);
+
+extern SATR CALPKXECMultAdd(const SATUINT32_t* puiMul, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtPCompress, SATUINT32_t uiPtQCompress,
+ SATUINT32_t* puiRx, SATUINT32_t* puiRy);
+
+extern SATR CALPKXECDSASign(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx,const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASignTwistCM(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSigR,
+ SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHCM(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiK,
+ const SATUINT32_t* puiD, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS, SATUINT32_t uiDMAChConfig,
+ const SATBOOL bCM);
+
+extern SATR CALPKXECDSASTwistH(const SATUINT32_t* puiHash,
+ const SATHASHTYPE eHashType, const SATUINT32_t* puiGx, const SATUINT32_t* puiGy,
+ const SATUINT32_t* puiK, const SATUINT32_t* puiD, const SATUINT32_t* puiB,
+ const SATUINT32_t* puiZ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, const SATUINT32_t uiLen,
+ SATUINT32_t* puiSigR, SATUINT32_t* puiSigS);
+
+extern SATR CALPKXECDSASTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiK, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t* puiSigR, SATUINT32_t* puiSigS,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVerify(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVerifyTwist(const SATUINT32_t* puiHash,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB,const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN, const SATUINT32_t* puiNMu,
+ const SATUINT32_t uiLen, const SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB,const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiLen,
+ SATUINT32_t uiPtCompress, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDSAVTwistH(const SATUINT32_t* puiHash, const SATHASHTYPE eHashType,
+ const SATUINT32_t* puiGx, const SATUINT32_t* puiGy, const SATUINT32_t* puiQx,
+ const SATUINT32_t* puiQy, const SATUINT32_t* puiSigR,
+ const SATUINT32_t* puiSigS, const SATUINT32_t* puiB, const SATUINT32_t* puiZ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, SATUINT32_t uiPtCompress);
+
+extern SATR CALPKXECDSAVTwistHDMA(const SATUINT32_t* puiExtInput,
+ SATHASHTYPE eHashType, SATUINT32_t uiMsgLen, const SATUINT32_t* puiGx,
+ const SATUINT32_t* puiGy, const SATUINT32_t* puiQx, const SATUINT32_t* puiQy,
+ const SATUINT32_t* puiSigR, const SATUINT32_t* puiSigS,
+ const SATUINT32_t* puiB, const SATUINT32_t* puiZ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECDHC(const SATUINT32_t* puiS, const SATUINT32_t* puiWx,
+ const SATUINT32_t* puiWy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, const SATUINT32_t* puiK, const SATUINT32_t* puiR,
+ const SATUINT32_t* puiRMu, SATUINT32_t uiLen, SATUINT32_t uiPtCompress,
+ SATUINT32_t* puiZ);
+
+extern SATR CALPKXRSACRT(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiP, const SATUINT32_t* puiPMu,
+ const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu, SATUINT32_t uiLen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTCM(const SATUINT32_t* puiCipher,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP,
+ const SATUINT32_t* puiDQ, const SATUINT32_t* puiE,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, const SATUINT32_t uiLen, const SATUINT32_t uiELen,
+ SATUINT32_t* puiPlain);
+
+extern SATR CALPKXRSACRTSign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiCipher, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ,
+ const SATUINT32_t* puiQMu, const SATUINT32_t* puiN, SATUINT32_t uiLen,
+ SATUINT32_t* puiS);
+
+extern SATR CALPKXRSACRTSignCM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSACRTSHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiQInv,
+ const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ, const SATUINT32_t* puiP,
+ const SATUINT32_t* puiPMu, const SATUINT32_t* puiQ, const SATUINT32_t* puiQMu,
+ const SATUINT32_t* puiN, SATUINT32_t uiMsgLen, SATUINT32_t uiModLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSACRTSHDMACM(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE, const SATUINT32_t uiELen,
+ const SATUINT32_t* puiQInv, const SATUINT32_t* puiDP, const SATUINT32_t* puiDQ,
+ const SATUINT32_t* puiP, const SATUINT32_t* puiQ, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen, SATUINT32_t uiLen,
+ SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSASign(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiD, const SATUINT32_t* puiN,
+ const SATUINT32_t* puiNMu, SATUINT32_t uiModLen, SATUINT32_t* puiSig);
+
+extern SATR CALPKXRSASHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiD,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, SATUINT32_t* puiSig, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXRSAVerify(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiHash, const SATUINT32_t* puiE, SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiModLen,
+ const SATUINT32_t* puiS);
+
+extern SATR CALPKXRSAVHDMA(SATRSAENCTYPE eRsaEncod, SATHASHTYPE eHashType,
+ const SATUINT32_t* puiExtInput, const SATUINT32_t* puiE,SATUINT32_t uiExpLen,
+ const SATUINT32_t* puiN, const SATUINT32_t* puiNMu, SATUINT32_t uiMsgLen,
+ SATUINT32_t uiModLen, const SATUINT32_t* puiS, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALPKXECPtValidate(const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiB, const SATUINT32_t* puiMod,
+ const SATUINT32_t* puiMu, SATUINT32_t uiLen);
+
+extern SATR CALPKXECKeyPairGen(const SATUINT32_t* puiC, const SATUINT32_t* puiPx,
+ const SATUINT32_t* puiPy, const SATUINT32_t* puiMod, const SATUINT32_t* puiMu,
+ const SATUINT32_t* puiNM1, const SATUINT32_t* puiNM1Mu, const SATUINT32_t* puiB,
+ SATUINT32_t* puiD, SATUINT32_t* puiQx, SATUINT32_t* puiQy, SATUINT32_t uiLen);
+
+extern SATR CALPKXPurge52(SATBOOL bVerify);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+extern SATRESULT SATResults;
+
+/* -------- ------ --------- */
+/* External Global Constants */
+/* -------- ------ --------- */
+extern const SATUINT32_t uiROMMods[];
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkxlib.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkxlib.h
new file mode 100644
index 0000000..fb4c0fc
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/pkxlib.h
@@ -0,0 +1,95 @@
+/* -------------------------------------------------------------------
+ $Rev: 1434 $ $Date: 2017-10-20 16:46:16 -0400 (Fri, 20 Oct 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for PKX-5200 Library.
+ ------------------------------------------------------------------- */
+
+#ifndef PKXLIB_H
+#define PKXLIB_H
+
+#include "caltypes.h"
+#include "calpolicy.h"
+
+#define PKX_JMP_NONE (0xFFFFu + PKX_OFFSET)
+
+/* jump table entry points: starting PC value */
+#define PKX_JMP_RECIP_PRECOMPUTE (0x0000 + PKX_OFFSET)
+#define PKX_JMP_MOD_EXP (0x0002 + PKX_OFFSET)
+#define PKX_JMP_RSA_CRT (0x0004 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL (0x0006 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN (0x0008 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_VERIFY (0x000A + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN (0x000C + PKX_OFFSET)
+#define PKX_JMP_DSA_VERIFY (0x000E + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT (0x0010 + PKX_OFFSET)
+#define PKX_JMP_MOD_RED (0x0012 + PKX_OFFSET)
+#define PKX_JMP_EC_PTDECOMP (0x0014 + PKX_OFFSET)
+#define PKX_JMP_EC_DHC (0x0016 + PKX_OFFSET)
+#define PKX_JMP_MOD_MULT_ADD (0x0018 + PKX_OFFSET)
+#define PKX_JMP_EC_PTMUL_ADD (0x001A + PKX_OFFSET)
+#define PKX_JMP_EC_PTVALIDATE (0x001C + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA (0x001E + PKX_OFFSET)
+#define PKX_JMP_F5200_AES (0x0020 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESK (0x0022 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM (0x0024 + PKX_OFFSET)
+#define PKX_JMP_F5200_GHA (0x0026 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKW (0x0028 + PKX_OFFSET)
+#define PKX_JMP_F5200_AESKWP (0x002A + PKX_OFFSET)
+#define PKX_JMP_RNG_INSTANTIATE (0x002C + PKX_OFFSET)
+#define PKX_JMP_RNG_RESEED (0x002E + PKX_OFFSET)
+#define PKX_JMP_RNG_GENERATE (0x0030 + PKX_OFFSET)
+#define PKX_JMP_RNG_UNINSTANTIATE (0x0032 + PKX_OFFSET)
+#define PKX_JMP_RNG_GETENTROPY (0x0034 + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_HMAC (0x0036 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_DMA (0x0038 + PKX_OFFSET)
+#define PKX_JMP_RNG_CTRLSTATUS (0x003A + PKX_OFFSET)
+#define PKX_JMP_F5200_SHA_DMA (0x003C + PKX_OFFSET)
+#define PKX_JMP_SHX_KEYTREE (0x003E + PKX_OFFSET)
+#define PKX_JMP_PKX_DSA_DMA (0x0040 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSACRT_SIGN (0x0042 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_SIGN (0x0044 + PKX_OFFSET)
+#define PKX_JMP_PKX_RSA_VERIFY (0x0046 + PKX_OFFSET)
+#define PKX_JMP_PKX_EC_DSA_DMA (0x0048 + PKX_OFFSET)
+#define PKX_JMP_F5200_AES_KEYROLL (0x004A + PKX_OFFSET)
+#define PKX_JMP_EXPM (0x004C + PKX_OFFSET)
+#define PKX_JMP_RSACRTM (0x004E + PKX_OFFSET)
+#define PKX_JMP_EC_PTMULM (0x0050 + PKX_OFFSET)
+#define PKX_JMP_DSA_SIGN_M (0x0052 + PKX_OFFSET)
+#define PKX_JMP_EC_DSA_SIGN_M (0x0054 + PKX_OFFSET)
+#define PKX_JMP_EC_KEYPAIRGEN (0x0056 + PKX_OFFSET)
+#define PKX_JMP_RSACRTCM_SIGN (0x0058 + PKX_OFFSET)
+#define PKX_JMP_F5200_GCM_NEW (0x005A + PKX_OFFSET)
+/* PKX PKRev 2180 */
+/* PKX SHARev 2160 */
+/* PKX AESRev 2135 */
+/* Hex Checksum: 0xd0d79866 */
+
+extern const SATUINT32_t uiPKX_Flags;
+extern const SATUINT32_t uiPKX_BERWords;
+extern const SATUINT32_t uiPKX_LIRWords;
+extern const SATUINT32_t uiPKX_Rev;
+extern const SATUINT32_t uiPKX_LibSize;
+extern const SATUINT32_t uiPKX_LibChksum;
+extern const SATUINT32_t uiPKX_Lib[];
+extern SATBOOL bMPF300TS_ES;
+
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/shaf5200.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/shaf5200.h
new file mode 100644
index 0000000..da598d1
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/shaf5200.h
@@ -0,0 +1,101 @@
+/* -------------------------------------------------------------------
+ $Rev: 1296 $ $Date: 2017-08-01 13:54:48 -0400 (Tue, 01 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for SHA function hardware implementation for CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SHAF5200_H
+#define SHAF5200_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+#ifndef SHAF5200_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern SATR shapkxctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen,void *pHash, const SATBOOL bFinal);
+
+extern SATR shapkxhmacctx(SATRESCONTEXTPTR const pContext, const void *pBuffer,
+ SATUINT32_t uiBufLen, void *pHash, const SATUINT8_t uiFlag);
+
+extern SATR shapkxctxload(SATRESCONTEXTPTR const pContext);
+
+extern void shapkxctxunload(SATRESCONTEXTPTR const pContext);
+
+extern SATR shapkxini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen);
+
+extern SATR shapkxhmacini(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pKey, SATUINT32_t uiKeyLen);
+
+extern SATR shapkxwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxhmacwrite(const void *pBuffer, SATUINT32_t uiBufLen);
+
+extern SATR shapkxread(void *pHash, SATUINT32_t uiRevFlag);
+
+extern SATR shapkxkeytree(SATBOOL bPathSizeSel, const SATUINT32_t* puiKey,
+ SATUINT8_t uiOpType, const SATUINT32_t* puiPath, SATUINT32_t* puiKeyOut);
+
+extern SATR shapkxdma(SATHASHTYPE eHashType, SATUINT32_t uiMsgLen,
+ const void *pExtSrc, const void *pExtDest, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhmacdma(SATMACTYPE eMACType, const SATUINT32_t *pKey,
+ SATUINT32_t uiKeyLen, const void *pMsg, SATUINT32_t uiMsgLen,
+ const void *pMAC, SATUINT32_t uiDMAChConfig);
+
+extern SATR shapkxhashtypeini(void);
+
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/sym.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/sym.h
new file mode 100644
index 0000000..2e07faa
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/sym.h
@@ -0,0 +1,129 @@
+/* -------------------------------------------------------------------
+ $Rev: 1292 $ $Date: 2017-07-26 15:12:11 -0400 (Wed, 26 Jul 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for Symmetric Key Cryptography in CAL.
+ ------------------------------------------------------------------- */
+
+#ifndef SYM_H
+#define SYM_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "calpolicy.h"
+#include "caltypes.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef SYM_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+extern SATR CALSymTrfRes(SATBOOL bBlock);
+
+extern SATR CALSymEncrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymDecrypt(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen);
+
+extern SATR CALSymEncryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymDecryptKR(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF);
+
+extern SATR CALSymEncryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecryptKRDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, SATBOOL bLoadIV, const void *pSrc,
+ void *pDest, SATUINT32_t uiLen, SATUINT32_t uiKRF, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymEncAuth(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymDecVerify(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen);
+
+extern SATR CALSymKw(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymKwp(SATSYMTYPE eSymType, const SATUINT32_t *puiKEK,
+ const SATUINT32_t *puiInKey, SATUINT32_t *puiOutKey, SATUINT32_t uiLen,
+ SATBOOL bWrap);
+
+extern SATR CALSymEncAuthDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+extern SATR CALSymDecVerifyDMA(SATSYMTYPE eSymType, const SATUINT32_t *puiKey,
+ SATSYMMODE eMode, void *pIV, const void *pSrc, void *pDest,
+ SATUINT32_t uiEncLen, void *pAuth, SATUINT32_t uiAuthLen, void *pMAC,
+ SATUINT32_t uiMACLen, SATUINT32_t uiDMAChConfig);
+
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/utils.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/utils.h
new file mode 100644
index 0000000..91474f0
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/utils.h
@@ -0,0 +1,93 @@
+/* -------------------------------------------------------------------
+ $Rev: 1300 $ $Date: 2017-08-07 11:36:02 -0400 (Mon, 07 Aug 2017) $
+ ------------------------------------------------------------------- */
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+
+/* -------------------------------------------------------------------
+ Description:
+ C header file for CAL utility functions.
+ ------------------------------------------------------------------- */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+/* -------- */
+/* Includes */
+/* -------- */
+#include "caltypes.h"
+#include "calenum.h"
+
+
+/* ------- */
+/* Defines */
+/* ------- */
+
+/* ---- ----------- */
+/* Type Definitions */
+/* ---- ----------- */
+
+/* -------- -------- ---------- */
+/* External Function Prototypes */
+/* -------- -------- ---------- */
+
+#ifndef UTILS_C
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Published API Functions */
+/* --------- --- --------- */
+
+/* Unpublished Function Prototypes */
+/* ----------- -------- ---------- */
+extern void CALMemCopy(void *pDst, const void *pSrc, SATUINT32_t uiNum8);
+
+extern void CALMemClear( void * pLoc, SATUINT32_t uiNum );
+
+extern void CALMemClear32( SATUINT32_t* puiLoc, SATUINT32_t uiLen32 );
+
+extern SATBOOL CALMemCmp(const void *pA, const void *pB, SATUINT32_t uiNum);
+
+extern void CALVol32MemLoad(volatile SATUINT32_t * puiDst, const void * pSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALVol32MemRead(void * pDst, volatile SATUINT32_t * puiSrc,
+ SATUINT32_t uiNum32);
+
+extern void CALByteReverse(SATUINT32_t* puiArray, SATINT32_t iNumberBytes);
+
+extern void CALByteReverseWord(SATUINT32_t* puiArray, SATINT32_t iNumberWords);
+
+extern void CALWordReverse(SATUINT32_t *puiArray, SATINT32_t iNumberWords);
+
+extern void vAppendNonzero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+extern void vAppendZero(void *puiArray, SATUINT32_t uiLen,
+ SATUINT32_t uiBlockSize);
+
+/* -------- ------ --------- */
+/* External Global Variables */
+/* -------- ------ --------- */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/middleware/cal/x52cfg_user.h b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/x52cfg_user.h
new file mode 100644
index 0000000..c8d8648
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/middleware/cal/x52cfg_user.h
@@ -0,0 +1,72 @@
+/* ----------- MERCURY SYSTEMS INC IP PROTECTION HEADER ----------------
+* (c) Mercury Systems, Inc. 2020. All rights reserved.
+* Mercury Proprietary Information
+*
+*
+* This file, the information contained herein, and its documentation are
+* proprietary to Mercury Systems, Inc. This file, the information contained
+* herein, and its documentation may only be used, duplicated, or disclosed
+* in accordance with the terms of a written license agreement between the
+* receiving party and Mercury or the receiving party and an authorized
+* licensee of Mercury.
+*
+* Each copy of this file shall include all copyrights, trademarks, service
+* marks, and proprietary rights notices, if any.
+*
+* ------------ MERCURY SYSTEMS INC IP PROTECTION HEADER --------------*/
+/* X5200 configuration */
+/* $Date: 2015-07-23 14:30:19 -0400 (Thu, 23 Jul 2015) $ $Rev: 2093 $ */
+/* -------------------------------------------------------------------
+ Options:
+ * LIR ROM size : 4096
+ * LIR RAM size : 2048
+ * BER size : 1024
+ * MMR size : 1024
+ * TSR size : 1024
+ * FPR size : 1024
+ * Single error correct, dual error detect (SECDED) memory parity
+ * DMA enabled
+ * FPGA multipliers disabled
+ * AES enabled
+ - Fast key schedule generation
+ - GCM/GHASH enabled
+ - AES countermeasures enabled
+ * RNG enabled
+ * External PRNG disabled
+ * SHA enabled
+ - Fast SHA enabled
+ - SHA-1 enabled
+ - SHA-224 enabled
+ - SHA-256 enabled
+ - SHA-384 enabled
+ - SHA-512 enabled
+ - SHA-512/224 enabled
+ - SHA-512/256 enabled
+ - SHA countermeasures enabled
+ * P-curves populated in FCR:
+ - P-192 populated
+ - P-224 populated
+ - P-256 populated
+ - P-384 populated
+ - P-521 populated
+ * Data memory scrambling enabled
+
+ ------------------------------------------------------------------- */
+
+#ifndef X52CFG_H
+#define X52CFG_H
+
+#define X52_CFG_MODEL 0xf5200
+#define X52_CFG_DATE 0x15072720
+#define X52_CFG_REV 0x0000082e
+#define X52_CFG_OPT 0x0fd87ff9
+#define X52_CFG_OPT2 0xc0000000
+#define X52_LIR_LEN 0x1800
+#define X52_LIR_ROM_LEN 0x1000
+#define X52_LIR_RAM_LEN 0x0800
+#define X52_BER_LEN 0x400
+#define X52_MMR_LEN 0x400
+#define X52_TSR_LEN 0x400
+#define X52_FPR_LEN 0x400
+
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/README.md b/user-crypto/miv-rv32-message-authentication/src/platform/README.md
new file mode 100644
index 0000000..f7f6030
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/README.md
@@ -0,0 +1,27 @@
+# Mi-V soft processor platform source code
+
+## Repo organization
+
+```
+
+ |
+ |-- drivers
+ | |- fpga_ip
+ | | | CoreGPIO
+ | | | CoreSysServices_PF
+ | | | CoreUARTapb
+ | |
+ | |- off_chip
+ | | | .
+ | | | .
+ | |
+ |-- hal
+ | |
+ |-- miv_rv32_hal
+
+
+```
+
+The drivers published here are compatible with the improved SoftConsole project folder structure being used in the latest [example projects](https://github.com/Mi-V-Soft-RISC-V/miv-rv32-bare-metal-examples).
+These drivers can also be used with the legacy folder structure (projects released via Firmware Catalog) by defining the **LEGACY_DIR_STRUCTURE** macro in the SoftConsole project settings.
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
new file mode 100644
index 0000000..1a0073f
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.c
@@ -0,0 +1,533 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
new file mode 100644
index 0000000..88ba178
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/core_gpio.h
@@ -0,0 +1,722 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 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 individual IOs of CoreGPIO 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 part of the hardware are 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 is
+ going to be used as input, output, or both. GPIO ports configured as inputs
+ are further configured to generate interrupts based on the state of input.
+ Interrupts is either level- or edge-sensitive.
+ Note that a CoreGPIO hardware instance is 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
+
+#ifdef __cplusplus
+extern "C" {
+#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;
+
+/*-------------------------------------------------------------------------*//**
+ Possible width of the APB bus
+ */
+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;
+
+/*-------------------------------------------------------------------------*//**
+ Structure instance holding all data regarding the CoreGPIO
+ */
+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 are also be used to identity GPIO through logical operations
+ on the return value of function GPIO_get_inputs().
+ # GPIO_0_MASK
+ # GPIO_1_MASK
+ # GPIO_2_MASK
+ # GPIO_3_MASK
+ # GPIO_4_MASK
+ # GPIO_5_MASK
+ # GPIO_6_MASK
+ # GPIO_7_MASK
+ # GPIO_8_MASK
+ # GPIO_9_MASK
+ # GPIO_10_MASK
+ # GPIO_11_MASK
+ # GPIO_12_MASK
+ # GPIO_13_MASK
+ # GPIO_14_MASK
+ # GPIO_15_MASK
+ # GPIO_16_MASK
+ # GPIO_17_MASK
+ # GPIO_18_MASK
+ # GPIO_19_MASK
+ # GPIO_20_MASK
+ # GPIO_21_MASK
+ # GPIO_22_MASK
+ # GPIO_23_MASK
+ # GPIO_24_MASK
+ # GPIO_25_MASK
+ # GPIO_26_MASK
+ # GPIO_27_MASK
+ # GPIO_28_MASK
+ # GPIO_29_MASK
+ # GPIO_30_MASK
+ # GPIO_31_MASK
+ */
+#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
+ * # GPIO_INPUT_MODE
+ * # GPIO_OUTPUT_MODE
+ * # GPIO_INOUT_MODE
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ * # GPIO_IRQ_LEVEL_HIGH
+ * # GPIO_IRQ_LEVEL_LOW
+ * # GPIO_IRQ_EDGE_POSITIVE
+ * # GPIO_IRQ_EDGE_NEGATIVE
+ * # GPIO_IRQ_EDGE_BOTH
+ */
+#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 initializes a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Note that a CoreGPIO hardware instance is 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 is used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that must perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the memory map of the
+ processor 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 are visible
+ as 8, 16, or 32-bits registers. Allowed values 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 the 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
+ interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as an 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.
+
+ @example
+ For example, the following call configures GPIO 4 as an input that generates
+ 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 the 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 GPIO must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ @example
+ Set GPIO 0 and 8 outputs high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ @example
+ Set GPIO 2 and 4 outputs low without affecting the 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 an output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that has 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 sets the output low, and a value of 1 sets 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 the 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 represents the state of
+ GPIO 0, and the most significant bit represents 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 the 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 represents the state
+ of GPIO 0, and the most significant bit represents 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 is in one of three states:
+ - high
+ - low
+ - high impedance
+
+ An INOUT output is typically be used where several devices drive the state of
+ a signal. The high and low states are equivalent to the high and low states of
+ a GPIO configured as an 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.
+ 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 the 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 a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_enable_irq() enables 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 allows 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 interrupts from being
+ generated based on the state of the input specified as a parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure
+ holding all the data regarding the CoreGPIO instance controlled through this
+ function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input that the call to
+ GPIO_disable_irq() disables 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 prevents 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 a 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 from re-triggering a call to the GPIO ISR.
+ 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 the 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 the
+ interrupt. i.e. to That is 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 the 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 a 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 all the active
+ interrupts generated by the GPIO specified as a 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
+ from re-triggering a call to the GPIO ISR.
+ 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 the 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 clear the interrupt bit register of the
+ corresponding GPIO bit. The least significant bit represents the status of
+ GPIO 0, and the most significant bit represents 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
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_GPIO_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
new file mode 100644
index 0000000..41f5b7c
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
new file mode 100644
index 0000000..1fd3dd6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.c
@@ -0,0 +1,1495 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C software driver implementation.
+ *
+ */
+
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+ saved_psr = HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+ saved_psr = HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+ saved_psr = HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
new file mode 100644
index 0000000..3891ce0
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_i2c.h
@@ -0,0 +1,2306 @@
+/***************************************************************************//**
+ * Copyright 2009-2023 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.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The CoreI2C driver provides a set of functions for controlling the Microchip
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it to operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus), and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver:
+ - Provides support to configuring the I2C channels of each CoreI2C peripheral device.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver is used as part of a bare metal system where no operating
+ system is available. The driver gets adapted 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 this driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and the I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized by I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ Apart from the CoreI2C hardware instance base address, no CoreI2C hardware configuration
+ parameters are used by the driver. Hence, no additional configuration files are required
+ to use the driver.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are available in the i2c_interrupt.c file.
+ The default implementation calls HAL_ASSERT(0) to indicate to the application
+ developer that a suitable implementations for these functions must be provided.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. See the provided example
+ projects for a working implementation of these functions.
+
+ The I2C_register_write_handler() function registers a write handler
+ function with the CoreI2C driver that calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project's compiler settings. The details of how to do this will depend
+ on your development software.
+
+ --------------------------------
+ SMBus Logic Options
+ --------------------------------
+ SMBus related APIs does not have any effect if the "Generate SMBus Logic"
+ is not enabled in the CoreI2C hardware configuration. Following are API's
+ that does not give the desired results if SMBus Logic is disabled.
+
+ - I2C_smbus_init()
+ - I2C_reset_smbus()
+ - I2C_enable_smbus_irq()
+ - I2C_disable_smbus_irq()
+ - I2C_suspend_smbus_slave()
+ - I2C_resume_smbus_slave()
+ - I2C_set_smsbus_alert()
+ - I2C_clear_smsbus_alert()
+ - I2C_get_irq_status()
+
+ --------------------------------
+ Fixed Baud Rate Values
+ --------------------------------
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ -----------------------------------
+ Fixed Slave Address Options Values
+ -----------------------------------
+ The primary slave address parameter passed to the I2C_init() function and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised by calling I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to the subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read, and write-read
+ transactions
+ - I2C slave operations functions to handle write, read, and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The CoreI2C device is first initialized by calling the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() function initializes channel 0 of a CoreI2C and the i2c_instance_t
+ for channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the channels.
+ Ensure to call I2C_init() function before calling any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address assigned
+ to the I2C and the serial clock divider to generate its I2C clock as configuration
+ parameters.
+
+ I2C_channel_init() function takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized by calling the I2C_init() and a pointer
+ to a separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which generates
+ its I2C clock.
+
+ --------------------------------
+ Interrupt Control
+ --------------------------------
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The I2C_register_write_handler() function is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ ## I2C Slave Addressing Functions
+ A CoreI2C peripheral responds to the following three slave addresses:
+ - Slave address 0 - This is the primary slave address that accesses
+ a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address using I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address is configured by
+ I2C_set_slave_second_addr() and is disabled by
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ --------------------------------
+ Transaction Types
+ --------------------------------
+ The I2C driver is designed to handle three types of I2C transaction:
+ - Write transactions
+ - Read transactions
+ - Write-read transactions
+
+ ## Write Transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge the receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge the receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Write-Read Transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit in between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ## Master Operations
+ The application can use the I2C_write(), I2C_read(), and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function is used to set a time base for the
+ I2C_wait_complete() function's time out delay.
+
+ ## Slave Operations
+ To configure the I2C driver to operate as an I2C slave requires the use
+ of the following functions:
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_set_slave_mem_offset_length()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ ## Responding to Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ • I2C_set_slave_tx_buffer()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_tx_buffer() function specifies the data buffer that
+ is transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to the I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write Transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ • I2C_set_slave_rx_buffer()
+ • I2C_register_write_handler()
+ • I2C_enable_slave()
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stored the data received by the I2C slave when it targets an I2C write
+ transaction.
+
+ The I2C_register_write_handler() function specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The I2C_enable_slave() function enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ ## Responding to Write-Read Transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ - I2C_set_slave_mem_offset_length()
+ - I2C_set_slave_tx_buffer()
+ - I2C_set_slave_rx_buffer()
+ - I2C_register_write_handler()
+ - I2C_enable_slave()
+
+ The I2C_set_slave_mem_offset_length() function specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The I2C_set_slave_tx_buffer() function specifies the data that is
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function. It decides which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The I2C_set_slave_rx_buffer() function specifies the data buffer that
+ stores the data received by the I2C slave during the write phase of
+ the write-read transaction. This buffer must be large enough to accommodate
+ the number of bytes specified through the I2C_set_slave_mem_offset_length()
+ function.
+
+ The I2C_register_write_handler() function can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The I2C_enable_slave() function enables the CoreI2C hardware instance to
+ respond to the I2C transactions. It must be called after configuring the
+ CoreI2C driver to respond to the required transaction types.
+
+ ## Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queues the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ ## SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used with a master mode CoreI2C
+ to force slave devices on the SMBus to enter their Power-Down/Suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used with a master mode CoreI2C to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used by a slave mode CoreI2C to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function clears the alert
+ condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ I2C_RELEASE_BUS
+ =======================================
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_HOLD_BUS
+ =======================================
+ The I2C_HOLD_BUS constant specify the options parameter to functions I2C_read(),
+ I2C_write(), and I2C_write_read() to indicate that a STOP bit must not be
+ generated at the end of the I2C transaction in order to retain the bus ownership.
+ This causes the next transaction to begin with a repeated START bit and no STOP
+ bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ Interrupt Identifier Number
+ =======================================
+ The following constants specify the interrupt identifier number which is
+ solely used by the driver API. This has nothing to do with hardware interrupt
+ line. I2C_INTR_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBSUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+
+ | Constant | Description |
+ |--------------------|--------------------------------------------------------|
+ | I2C_NO_IRQ | No interrupt |
+ | I2C_SMBALERT_IRQ | Used by SMBus interrupt enable functions |
+ | I2C_SMBSUS_IRQ | Used by SMBus interrupt disable functions |
+ | I2C_INTR_IRQ | Primary interrupt signal which drives the state machine|
+
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ I2C_NO_TIMEOUT
+ =======================================
+ The I2C_wait_complete() function uses I2C_NO_TIMEOUT constant as a parameter
+ to indicate that the wait for completion of the transaction should not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/***************************************************************************//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/***************************************************************************//**
+ The i2c_clock_divider_t type specifies the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/***************************************************************************//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/***************************************************************************//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+/***************************************************************************//**
+ This structure identifies various CoreI2C hardware instances in the system
+ and the I2C channels within them. The application software should declare
+ one instance of this structure for each channel of each instance of CoreI2C
+ in your system. I2C_init() and I2C_channel_init() functions initialize this
+ structure depending on whether it is channel 0 or one of the additional
+ channels, respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify which
+ CoreI2C hardware instance to use.
+ */
+typedef struct i2c_instance i2c_instance_t ;
+/***************************************************************************//*
+ Slave write handler functions prototype
+/***************************************************************************//**
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+
+ Slave write handler functions should follow the following prototype:
+ @code
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+ @endcode
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Define the INCLUDE_SLA_IN_RX_PAYLOAD macro for the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows the applications to tailor their response based on the actual
+ address used to access the slave (primary address, secondary address, or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ - I2C_REENABLE_SLAVE_RX
+ - I2C_PAUSE_SLAVE_RX
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content gets processed by some other part of the
+ software application.
+
+ Call the I2C_enable_slave() after returning the I2C_PAUSE_SLAVE_RX to release
+ the received data buffer in order to store the data received by the subsequent
+ I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+/***************************************************************************//**
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The I2C_init() function configures channel 0 of a CoreI2C instance. It sets
+ the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+
+ @param this_i2c
+ Pointer to the i2c_instance_t data structure that holds all the data
+ related to channel 0 of the CoreI2C instance is initialized. A pointer
+ to this structure is used in all subsequent calls to the CoreI2C driver
+ functions which operates on channel 0 of this CoreI2C instance.
+
+ @param base_address
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C to initialize. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then provide any dummy slave address value
+ to this parameter. However, in systems where the CoreI2C is expected to
+ switch from master mode to slave mode, it is advisable to initialize the
+ CoreI2C device with a valid serial slave address. Call the I2C_init()
+ function whenever it is required to change the primary slave address as
+ there is no separate function to set the primary slave address of the
+ I2C device. The serial address initialized through this function is
+ basically the primary slave address or slave address0.
+ I2C_set_slave_second_addr() is used to set the secondary slave address
+ or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that generates the serial clock from the APB PCLK or from the BCLK.
+ It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value overrides the value passed
+ as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ is used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure that holds all data related to
+ the CoreI2C channel gets initialized. A pointer to the same data structure
+ is used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c
+ This is a pointer to an i2c_instance_t structure, previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed
+ by this_i2c must be previously initialized by calling I2C_init().
+
+ @param channel_number
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that is used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ - I2C_PCLK_DIV_256
+ - I2C_PCLK_DIV_224
+ - I2C_PCLK_DIV_192
+ - I2C_PCLK_DIV_160
+ - I2C_PCLK_DIV_960
+ - I2C_PCLK_DIV_120
+ - I2C_PCLK_DIV_60
+ - I2C_BCLK_DIV_8
+ Note: serial_clock_speed value does not have any affect if the fixed baud
+ rate is enabled in CoreI2C hardware instance configuration dialogue
+ window. The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/***************************************************************************//**
+ The I2C_isr function is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #Master Specific Functions
+
+ The following functions are only used within an I2C master's implementation.
+/***************************************************************************//**
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device. Do not to release the memory used by this buffer
+ before the write transaction completes. For example, it is not appropriate
+ to return from a function allocating this buffer as an auto array variable
+ before the write transaction completes as this would result in the buffer's
+ memory being de-allocated from the stack when the function returns. This
+ memory could then be subsequently reused and modified causing unexpected
+ data to be written to the target I2C device.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ gets stored. Do not to release the memory used by this buffer before the read
+ transaction completes. For example, it is not appropriate to return from a
+ function allocating this buffer as an auto array variable before the read
+ transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ applies to this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset
+ This parameter is a pointer to the buffer containing the data that is sent
+ to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed by the addr_offset parameter.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed by
+ the read_buffer parameter.
+
+ @param options
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/***************************************************************************//**
+ This function indicates the current state of a CoreI2C channel.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Following are the return values are:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms
+ The timeout_ms parameter specifies the delay within which the current I2C
+ transaction should complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ - I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ - I2C_FAILED
+ The last I2C transaction failed.
+ - I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/***************************************************************************//**
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function's time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+
+ Note: If this function is being called from an interrupt handler (for example,
+ SysTick) it is important that the calling interrupt have a lower priority
+ than the CoreI2C interrupt(s) to ensure any updates to the shared data are
+ protected.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+
+ @return None.
+
+ @example
+ The following example shows how the I2C_system_tick() function. I2C_system_tick()
+ is called for each I2C channel from the SysTick timer interrupt service routine.
+ The following example shows how the SysTick is configured to generate an interrupt
+ in every 10 milliseconds.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/***************************************************************************//*
+ #Slave Specific Functions
+
+ The following functions are only used within the implementation of an I2C slave device.
+
+/***************************************************************************//**
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size
+ Size of the transmit buffer pointed by the tx_buffer parameter.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/***************************************************************************//**
+ This function specifies the memory buffer that is used by the CoreI2C channel
+ to receive data when it is a slave. This buffer is the memory where data gets
+ stored when the CoreI2C channel is the target of an I2C master write
+ transaction (that is, when it is the slave).
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size
+ Size of the slave receive buffer. This is the amount of memory allocated
+ to the buffer pointed by rx_buffer.
+ Note: Indirectly, this buffer size specifies the maximum I2C write
+ transaction length this CoreI2C channel targets. This is because
+ this CoreI2C channel responds to further received bytes with
+ a non-acknowledge bit (NACK) as soon as its receive buffer is
+ full. This causes the write transaction to fail.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/***************************************************************************//**
+ This function is used as part of the configuration of a CoreI2C channel to
+ operate as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+ • If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+ • If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8-bit offset value in the range 0 to 255.
+ • If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16-bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+ If the number of bytes received does not match the non 0 value of
+ offset_length, the transmit buffer offset is set to 0.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/***************************************************************************//**
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that is transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write-read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler
+ Pointer to the function that processes the I2C write request.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/***************************************************************************//**
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write,
+ or write-read transaction.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ This function disables the slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave that acknowledges the I2C read, write, or write-read
+ transactions targeted at it.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_slave_second_addr() function sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address required in certain
+ applications, for example, to enable fail-safe operation in a system. As the
+ CoreI2C device supports 7-bit addressing, the highest value assigned to second
+ slave address is 127 (0x7F).
+
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/***************************************************************************//**
+ The I2C_disable_slave_second_addr() function disables the secondary slave
+ address of the CoreI2C slave device.
+
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device to respond to a general call or broadcast message from an I2C master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//*
+ #I2C SMBUS Specific APIs
+
+/***************************************************************************//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function then enables the IPMI 3mS SCL low timeout but
+ none of the other SMBus functions will have any effect.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ - I2C_SMBALERT_IRQ
+ - I2C_SMBSUS_IRQ
+ To enable both interrupts in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_disable_smbus_irq() function disable the CoreI2C channel’s SMBSUS and
+ SMBALERT SMBus interrupts.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which are disabled.
+ The two possible interrupts are:
+ • I2C_SMBALERT_IRQ
+ • I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/***************************************************************************//**
+ The I2C_suspend_smbus_slave() function forces any SMBUS slave devices
+ connected to a CoreI2C channel into Power-Down or Suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_resume_smbus_slave() function de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of the Suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35 mS. The reset that automatically cleares after 35 ms
+ gets elapsed. The CoreI2C channel is the SMBus master in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel's SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_clear_smbus_alert() function is used to de-assert the CoreI2C channel's
+ SMBALERT signal once a slave device gets a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_get_irq_status function returns information about which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ • SMBUSALERT
+ • SMBSUS
+ • INTR
+
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ, and I2C_INTR_IRQ are
+ provided to use with this function.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel's interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/***************************************************************************//**
+ The I2C_set_user_data() function allows the association of a block of application
+ specific data with a CoreI2C channel. The composition of the data block is an
+ application matter and the driver simply provides the means for the application
+ to set and retrieve the pointer. For example, this is used to provide additional
+ channel specific information to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ None.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/***************************************************************************//**
+ The I2C_get_user_data() function is used to allows the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ For example, this is used to provide additional channel specific information
+ to the slave write handler.
+
+ @param this_i2c
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ @example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
new file mode 100644
index 0000000..b1d872d
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
new file mode 100644
index 0000000..12e352d
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2009-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreI2C driver interrupt control.
+ *
+ */
+#include "core_i2c.h"
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ HAL_ASSERT(0)
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
new file mode 100644
index 0000000..2e11750
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * CoreSPI bare metal driver implementation for CoreSPI.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * @file core_spi.c
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI software configuration
+ *
+ */
+
+#include "core_spi.h"
+#include "corespi_regs.h"
+#include
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0u )
+#define NULL_INSTANCE ( ( spi_instance_t * ) 0u )
+#define NULL_BUFF ( ( uint8_t * ) 0u )
+#define NULL_FRAME_HANDLER ( ( spi_frame_rx_handler_t ) 0u )
+#define NULL_BLOCK_HANDLER ( ( spi_block_rx_handler_t ) 0u )
+#define NULL_SLAVE_TX_UPDATE_HANDLER ( ( spi_slave_frame_tx_handler_t ) 0u )
+#define NULL_SLAVE_CMD_HANDLER NULL_BLOCK_HANDLER
+
+#define SPI_ALL_INTS (0xFFu) /* For clearing all active interrupts */
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+
+#define DISABLE 0u
+#define ENABLE 1u
+
+
+/*******************************************************************************
+ * Function return values
+ */
+enum {
+ FAILURE = 0u,
+ SUCCESS = 1u
+};
+
+/*******************************************************************************
+ * Local function declarations
+ */
+static void fill_slave_tx_fifo( spi_instance_t * this_spi );
+static void read_slave_rx_fifo( spi_instance_t * this_spi );
+static void recover_from_rx_overflow( const spi_instance_t * this_spi );
+
+/*******************************************************************************
+ * SPI_init()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_ADDR != base_addr );
+ HAL_ASSERT( SPI_MAX_FIFO_DEPTH >= fifo_depth );
+ HAL_ASSERT( SPI_MIN_FIFO_DEPTH <= fifo_depth );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( base_addr != NULL_ADDR ) )
+ {
+ /*
+ * Initialize all transmit / receive buffers and handlers
+ *
+ * Relies on the fact that byte filling with 0x00 will equate
+ * to 0 for any non byte sized items too.
+ */
+
+ /* First fill struct with 0s */
+ memset( this_spi, 0, sizeof(spi_instance_t) );
+
+ /* Configure CoreSPI instance attributes */
+ this_spi->base_addr = (addr_t)base_addr;
+
+ /* Store FIFO depth or fall back to minimum if out of range */
+ if( ( SPI_MAX_FIFO_DEPTH >= fifo_depth ) && ( SPI_MIN_FIFO_DEPTH <= fifo_depth ) )
+ {
+ this_spi->fifo_depth = fifo_depth;
+ }
+ else
+ {
+ this_spi->fifo_depth = SPI_MIN_FIFO_DEPTH;
+ }
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Ensure all slaves are deselected */
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, 0u );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in the reset default of master mode
+ * with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled.
+ * The driver does not currently use interrupts in master mode.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_slave_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Don't yet know what slave transfer mode will be used */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Make sure the CoreSPI is disabled while we configure it */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+ /*
+ * Enable the CoreSPI in slave mode with TXUNDERRUN, RXOVFLOW and TXDONE
+ * interrupts disabled. The appropriate interrupts will be enabled later
+ * on when the transfer mode is configured.
+ */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_configure_master_mode()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the CoreSPI for a little while, while we configure the CoreSPI */
+ HAL_set_8bit_reg_field(this_spi->base_addr, CTRL1_ENABLE, DISABLE);
+
+ /* Reset slave transfer mode to unknown in case it has been set previously */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_NONE;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Ensure RXAVAIL, TXRFM, SSEND and CMDINT are disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, 0u );
+
+ /* Enable the CoreSPI in master mode with TXUNDERRUN, RXOVFLOW and TXDONE interrupts disabled */
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL1, ENABLE | CTRL1_MASTER_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t)(0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW ) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Set the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) | ((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_clear_slave_select()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+)
+{
+ spi_slave_t temp = (spi_slave_t) (0x00u) ;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( SPI_MAX_NB_OF_SLAVES > slave );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( SPI_MAX_NB_OF_SLAVES > slave ) )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+ /* Clear the correct slave select bit */
+ temp = (spi_slave_t)( HAL_get_8bit_reg( this_spi->base_addr, SSEL ) & ~((uint32_t)1u << (uint32_t)slave) );
+ HAL_set_8bit_reg( this_spi->base_addr, SSEL, (uint_fast8_t)temp ) ;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+)
+{
+ volatile uint32_t rx_data = 0u; /* Ensure consistent return value if in slave mode */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Flush the receive and transmit FIFOs by resetting both */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Send frame. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, tx_bits );
+
+ /* Wait for frame Tx to complete. */
+ while ( ENABLE != HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_DONE ) )
+ {
+ ;
+ }
+
+ /* Read received frame. */
+ rx_data = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ }
+ }
+
+ /* Finally, return the frame we received from the slave or 0 */
+ return( rx_data );
+}
+
+
+/***************************************************************************//**
+ * SPI_transfer_block()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave but we still have to keep discarding any read data that
+ * corresponds with one of our command bytes.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read and discard. */
+ HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received byte. */
+ rx_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_transfer_block_store_all_resp()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+)
+{
+ uint32_t transfer_size = 0U; /* Total number of bytes to transfer. */
+ uint16_t transfer_idx = 0U; /* Number of bytes transferred so far */
+ uint16_t tx_idx = 0u; /* Number of valid data bytes sent */
+ uint16_t rx_idx = 0u; /* Number of valid response bytes received */
+ uint16_t transit = 0U; /* Number of bytes "in flight" to avoid FIFO errors */
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI master. */
+ if( ( DISABLE != HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) ) &&
+ /* Check for empty transfer as well */
+ ( 0u != ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) ) )
+ {
+ /*
+ * tansfer_size is one less than the real amount as we have to write
+ * the last frame separately to trigger the slave deselect in case
+ * the SPS option is in place.
+ */
+ transfer_size = ( (uint32_t)cmd_byte_size + (uint32_t)rx_byte_size ) - 1u;
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, (uint32_t)(CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK ));
+
+ /* Recover from receiver overflow because of previous slave */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXOVFLOW) )
+ {
+ recover_from_rx_overflow( this_spi );
+ }
+
+ /* Disable the Core SPI for a little bit, while we load the TX FIFO */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ while( ( tx_idx < transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out 0s to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ }
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* If room left to put last frame in before the off, then do it */
+ if( ( tx_idx == transfer_size ) && ( tx_idx < this_spi->fifo_depth ) )
+ {
+ if( tx_idx < cmd_byte_size )
+ {
+ /* Push out valid data, not expecting any reply this time */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ /* Push out last 0 to get data back from slave */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ }
+
+ ++transit;
+ ++tx_idx;
+ }
+
+ /* FIFO is all loaded up so enable Core SPI to start transfer */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+
+ /* Perform the remainder of the transfer by sending a byte every time a byte
+ * has been received. This should ensure that no Rx overflow can happen in
+ * case of an interrupt occurring during this function.
+ *
+ * We break the transfer down into stages to minimise the processing in
+ * each loop as the SPI interface is very demanding at higher clock rates.
+ * This works well with FIFOs but might be less efficient if there is only
+ * a single frame buffer.
+ *
+ * First stage transfers remaining command bytes (if any).
+ * At this stage anything in the RX FIFO can be discarded as it is
+ * not part of a valid response.
+ */
+ while( tx_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ /* Send another byte. */
+ if( tx_idx == transfer_size ) /* Last frame is special... */
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ else
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)cmd_buffer[tx_idx] );
+ }
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now, we are writing dummy bytes to push through the response from
+ * the slave, which we store in the command response buffer.
+ */
+ while( transfer_idx < cmd_byte_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ if( tx_idx < transfer_size )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received command byte. */
+ cmd_response_buffer[transfer_idx] = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Now we are now only sending dummy data to push through the
+ * valid response data which we store in the data response buffer.
+ */
+ while( tx_idx < transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /* If we still need to send the last frame */
+ while( tx_idx == transfer_size )
+ {
+ if( transit < this_spi->fifo_depth )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, 0U );
+ ++tx_idx;
+ ++transit;
+ }
+ if( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ --transit;
+ }
+ }
+ /*
+ * Finally, we are now finished sending data and are only reading
+ * valid response data which we store in the data response buffer.
+ */
+ while( transfer_idx <= transfer_size )
+ {
+ if( !HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Process received data byte. */
+ rx_data_buffer[rx_idx] = (uint8_t)HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ ++rx_idx;
+ ++transfer_idx;
+ }
+ }
+ }
+ }
+}
+/***************************************************************************//**
+ * SPI_set_frame_rx_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if(NULL_INSTANCE != this_spi)
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if(DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER))
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Disable block Rx handler as they are mutually exclusive. */
+ this_spi->block_rx_handler = 0U;
+
+ /* Keep a copy of the pointer to the Rx handler function. */
+ this_spi->frame_rx_handler = rx_handler;
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no tx frame handler is set at this point in time...
+ *
+ * Don't allow TXDONE interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, DISABLE );
+ }
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Enable Rx and FIFO error interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Finally re-enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_tx_frame()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Disable SSEND and CMD interrupts as we are not doing block transfers */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ if( SPI_SLAVE_XFER_FRAME != this_spi->slave_xfer_mode )
+ {
+ /*
+ * Either just coming from init or were previously in block mode
+ * so no rx frame handler is set at this point in time...
+ *
+ * Don't allow RXDATA interrupts.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, DISABLE );
+ }
+
+ /* Disable slave block tx buffer as it is mutually exclusive with frame
+ * level handling. */
+ this_spi->slave_tx_buffer = NULL_BUFF;
+ this_spi->slave_tx_size = 0U;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs*/
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK);
+
+ /* Assign the slave frame update handler - NULL_SLAVE_TX_UPDATE_HANDLER for none */
+ this_spi->slave_tx_frame_handler = slave_tx_frame_handler;
+
+ /* Keep a copy of the slave Tx frame value. */
+ this_spi->slave_tx_frame = frame_value;
+
+ /* Load one frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+
+ /* Enable Tx Done interrupt in order to reload the slave Tx frame after each
+ * time it has been sent. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXDONE, ENABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_FRAME;
+
+ /* Ready to go so enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_slave_block_buffers()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* This function is only intended to be used with an SPI slave. */
+ if( DISABLE == HAL_get_8bit_reg_field(this_spi->base_addr, CTRL1_MASTER ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Make sure correct mode is selected */
+ this_spi->slave_xfer_mode = SPI_SLAVE_XFER_BLOCK;
+ /*
+ * No command handler should be setup at this stage so fake this
+ * to ensure 0 padding works.
+ */
+ this_spi->cmd_done = 1u;
+
+ /* Disable frame handlers as they are mutually exclusive with block Rx handler. */
+ this_spi->frame_rx_handler = NULL_FRAME_HANDLER;
+ this_spi->slave_tx_frame_handler = NULL_SLAVE_TX_UPDATE_HANDLER;
+
+ /* Keep a copy of the pointer to the block Rx handler function. */
+ this_spi->block_rx_handler = block_rx_handler;
+
+ /* Assign slave receive buffer */
+ this_spi->slave_rx_buffer = rx_buffer;
+ this_spi->slave_rx_size = rx_buff_size;
+ this_spi->slave_rx_idx = 0U;
+
+ /* Assign slave transmit buffer*/
+ this_spi->slave_tx_buffer = tx_buffer;
+ this_spi->slave_tx_size = tx_buff_size;
+ this_spi->slave_tx_idx = 0U;
+
+ /* Flush the receive and transmit FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Preload the transmit FIFO. */
+ while( !(HAL_get_8bit_reg_field(this_spi->base_addr, STATUS_TXFULL)) &&
+ ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Disable TXDATA interrupt as we will look after transmission in rx handling
+ * because we know that once we have read a frame it is safe to send another one.
+ */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTTXDATA, DISABLE );
+
+ /* Enable Rx, FIFO error and SSEND interrupts */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTRXOVFLOW, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_INTTXURUN, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTRXDATA, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTSSEND, ENABLE );
+
+ /* Disable command handler until it is set explicitly */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_handler()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+)
+{
+ uint32_t ctrl2 = 0u;
+
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_SLAVE_CMD_HANDLER != cmd_handler );
+ HAL_ASSERT( 0u < cmd_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < cmd_size ) &&
+ ( NULL_SLAVE_CMD_HANDLER != cmd_handler ) )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ /*
+ * Note we don't flush the FIFOs as this has been done already when
+ * block mode was configured.
+ *
+ * Clear this flag so zero padding is disabled until command response
+ * has been taken care of.
+ */
+ this_spi->cmd_done = 0u;
+
+ /* Assign user handler for Command received interrupt */
+ this_spi->cmd_handler = cmd_handler;
+
+ /* Configure the command size and Enable Command received interrupt */
+ ctrl2 = HAL_get_8bit_reg( this_spi->base_addr, CTRL2 );
+
+ /* First clear the count field then insert count and int enables */
+ ctrl2 &= ~(uint32_t)CTRL2_CMDSIZE_MASK;
+ ctrl2 |= (uint32_t)((cmd_size & CTRL2_CMDSIZE_MASK) | CTRL2_INTCMD_MASK | CTRL2_INTRXDATA_MASK);
+ HAL_set_8bit_reg( this_spi->base_addr, CTRL2, ctrl2 );
+
+ /* Now enable the CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * SPI_set_cmd_response()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ HAL_ASSERT( NULL_BUFF != resp_tx_buffer );
+ HAL_ASSERT( 0u < resp_buff_size );
+
+ if( ( NULL_INSTANCE != this_spi ) && ( 0u < resp_buff_size ) &&
+ ( NULL_BUFF != resp_tx_buffer ) )
+ {
+ this_spi->resp_tx_buffer = resp_tx_buffer;
+ this_spi->resp_buff_size = resp_buff_size;
+ this_spi->resp_buff_tx_idx = 0u;
+
+ fill_slave_tx_fifo(this_spi);
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_enable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI_disable()
+ * See "core_spi.h" for details of how to use this function.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+)
+{
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Disable the Core SPI while we configure */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+ }
+}
+
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+ int32_t guard;
+
+/*
+ * The assert and the NULL check here can be commented out to reduce the interrupt
+ * latency once you are sure the interrupt vector code is correct.
+ */
+ HAL_ASSERT( NULL_INSTANCE != this_spi );
+ if( NULL_INSTANCE != this_spi )
+ {
+ /* Handle receive. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_RXDATA ) )
+ {
+ /*
+ * Service receive data according to transfer mode in operation.
+ *
+ * We check block mode first as this is most likely to have back to back
+ * transfers with multiple bytes.
+ *
+ * Note the order of the checks here will effect interrupt latency and
+ * for critical timing the mode you are using most often should probably be
+ * be the first checked.
+ */
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Read irrespective to clear the RX IRQ */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ /*
+ * Now handle updating of tx FIFO to keep the data flowing.
+ * First see if there is anything in slave_tx_buffer to send.
+ */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+ /*
+ * Next see if there is anything in resp_tx_buffer to send.
+ */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size )
+ && ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+ /*
+ * Lastly, see if we are ready to pad with 0s .
+ */
+ if( this_spi->cmd_done && ( this_spi->slave_tx_idx >= this_spi->slave_tx_size ) &&
+ ( this_spi->resp_buff_tx_idx >= this_spi->resp_buff_size ) )
+ {
+ guard = 1 + ((int32_t)this_spi->fifo_depth / 4);
+ while( ( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ && ( 0 != guard ) )
+ {
+ /*
+ * Pad TX FIFO with 0s for consistent behaviour if the master
+ * tries to transfer more than we expected.
+ */
+ HAL_set_32bit_reg(this_spi->base_addr, TXDATA, 0x00u);
+ /*
+ * We use the guard count to cover the event that we are never
+ * seeing the TX FIFO full because the data is being pulled
+ * out as fast as we can stuff it in. In this case we never spend
+ * more than our allocated time spinning here.
+ */
+ guard--;
+ }
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Single frame handling mode. */
+ {
+ while( 0u == HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ /* Handle transmit. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXDONE ) )
+ {
+ /*
+ * Note, the driver only currently uses the txdone interrupt when
+ * in frame transmit mode. In block mode all TX handling is done by the
+ * receive interrupt handling code as we know that for every frame received
+ * a frame must be placed in the TX FIFO.
+ */
+ if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode )
+ {
+ /* Execute the user callback to update the slave_tx_frame */
+ if( NULL_SLAVE_TX_UPDATE_HANDLER != this_spi->slave_tx_frame_handler )
+ {
+ this_spi->slave_tx_frame_handler ( this_spi );
+ }
+
+ /* Reload slave tx frame into Tx data register. */
+ HAL_set_32bit_reg( this_spi->base_addr, TXLAST, this_spi->slave_tx_frame );
+ }
+ else if( SPI_SLAVE_XFER_BLOCK != this_spi->slave_xfer_mode )
+ {
+ /* Slave transfer mode not set up so discard anything in TX FIFO */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ }
+ else
+ {
+ /* Nothing to do, no slave mode configured */
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXDONE, ENABLE );
+ }
+
+
+ /* Handle receive overflow. */
+ if( ENABLE == HAL_get_8bit_reg_field(this_spi->base_addr, INTMASK_RXOVERFLOW))
+ {
+ HAL_set_8bit_reg(this_spi->base_addr, CMD, CMD_RXFIFORST_MASK);
+ HAL_set_8bit_reg_field(this_spi->base_addr, INTCLR_RXOVERFLOW, ENABLE);
+ }
+
+ /* Handle transmit under run. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_TXUNDERRUN ) )
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_TXUNDERRUN, ENABLE );
+ }
+
+ /* Handle command interrupt. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_CMDINT ) )
+ {
+ read_slave_rx_fifo( this_spi );
+
+ /*
+ * Call the command handler if one exists.
+ */
+ if( NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler )
+ {
+ this_spi->cmd_handler( this_spi->slave_rx_buffer, this_spi->slave_rx_idx );
+ }
+ this_spi->cmd_done = 1u;
+ /* Disable command interrupt until slave select becomes de-asserted to avoid retriggering. */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, DISABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ }
+
+ /* Handle slave select becoming de-asserted. */
+ if( ENABLE == HAL_get_8bit_reg_field( this_spi->base_addr, INTMASK_SSEND) )
+ {
+ /* Only supposed to do all this if transferring blocks... */
+ if(SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode)
+ {
+ uint32_t rx_size;
+
+ /* Empty any remaining bytes in RX FIFO */
+ read_slave_rx_fifo( this_spi );
+ rx_size = this_spi->slave_rx_idx;
+ /*
+ * Re-enable command interrupt if required.
+ * Must be done before re loading FIFO to ensure stale response
+ * data is not pushed into the FIFO.
+ */
+ if(NULL_SLAVE_CMD_HANDLER != this_spi->cmd_handler)
+ {
+ this_spi->cmd_done = 0u;
+ this_spi->resp_tx_buffer = 0u;
+ this_spi->resp_buff_size = 0u;
+ this_spi->resp_buff_tx_idx = 0u;
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_CMDINT, ENABLE );
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL2_INTCMD, ENABLE );
+ }
+ /*
+ * Reset the transmit index to 0 to restart transmit at the start of the
+ * transmit buffer in the next transaction. This also requires flushing
+ * the Tx FIFO and refilling it with the start of Tx data buffer.
+ */
+ this_spi->slave_tx_idx = 0u;
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+ fill_slave_tx_fifo( this_spi );
+
+ /* Prepare to receive next packet. */
+ this_spi->slave_rx_idx = 0u;
+ /*
+ * Call the receive handler if one exists.
+ */
+ if( NULL_BLOCK_HANDLER != this_spi->block_rx_handler )
+ {
+ this_spi->block_rx_handler( this_spi->slave_rx_buffer, rx_size );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_RXDATA, ENABLE );
+ }
+
+ HAL_set_8bit_reg_field( this_spi->base_addr, INTCLR_SSEND, ENABLE );
+ }
+ }
+}
+
+/*******************************************************************************
+ * Local function definitions
+ */
+
+/***************************************************************************//**
+ * Fill the transmit FIFO (used for slave block transfers).
+ */
+static void fill_slave_tx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ /* First see if slave_tx_buffer needs transmitting */
+ while( ( this_spi->slave_tx_idx < this_spi->slave_tx_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->slave_tx_buffer[this_spi->slave_tx_idx] );
+ ++this_spi->slave_tx_idx;
+ }
+
+ /* Then see if it is safe to look at putting resp_tx_buffer in FIFO? */
+ if( this_spi->slave_tx_idx >= this_spi->slave_tx_size )
+ {
+ while( ( this_spi->resp_buff_tx_idx < this_spi->resp_buff_size ) &&
+ !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_TXFULL ) )
+ {
+ HAL_set_32bit_reg( this_spi->base_addr, TXDATA, (uint32_t)this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx] );
+ ++this_spi->resp_buff_tx_idx;
+ }
+ }
+}
+
+/***************************************************************************//**
+ *
+ */
+static void read_slave_rx_fifo
+(
+ spi_instance_t * this_spi
+)
+{
+ uint32_t rx_frame;
+
+ if( SPI_SLAVE_XFER_BLOCK == this_spi->slave_xfer_mode ) /* Block handling mode. */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA ); /* Read irresepective to clear the RX IRQ */
+ if( this_spi->slave_rx_idx < this_spi->slave_rx_size )
+ {
+ this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame;
+ }
+ ++this_spi->slave_rx_idx;
+ }
+ }
+ else if( SPI_SLAVE_XFER_FRAME == this_spi->slave_xfer_mode ) /* Frame handling mode */
+ {
+ while( !HAL_get_8bit_reg_field( this_spi->base_addr, STATUS_RXEMPTY ) )
+ {
+ /* Single frame handling mode. */
+ rx_frame = HAL_get_32bit_reg( this_spi->base_addr, RXDATA );
+ if( NULL_FRAME_HANDLER != this_spi->frame_rx_handler )
+ {
+ this_spi->frame_rx_handler( rx_frame );
+ }
+ }
+ }
+ else /* Slave transfer mode not set up so discard anything in RX FIFO */
+ {
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_RXFIFORST_MASK );
+ }
+}
+
+/***************************************************************************//**
+ * This function is to recover the CoreSPI from receiver overflow.
+ * It temporarily disables the CoreSPI from interacting with external world, flushes
+ * the transmit and receiver FIFOs, clears all interrupts and then re-enables
+ * the CoreSPI instance referred by this_spi parameter.
+ */
+static void recover_from_rx_overflow
+(
+ const spi_instance_t * this_spi
+)
+{
+ /* Disable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, DISABLE );
+
+ /* Reset TX and RX FIFOs */
+ HAL_set_8bit_reg( this_spi->base_addr, CMD, CMD_TXFIFORST_MASK | CMD_RXFIFORST_MASK );
+
+ /* Clear all interrupts */
+ HAL_set_8bit_reg( this_spi->base_addr, INTCLR, SPI_ALL_INTS );
+
+ /* Enable CoreSPI */
+ HAL_set_8bit_reg_field( this_spi->base_addr, CTRL1_ENABLE, ENABLE );
+}
+
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
new file mode 100644
index 0000000..c6873f7
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/core_spi.h
@@ -0,0 +1,1324 @@
+/***************************************************************************//**
+ * Copyright 2013-2023 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.
+ *
+ * Core SPI bare metal software driver public API.
+ *
+ * This Core SPI driver provides functions for implementing SPI master or
+ * SPI slave operations with the CoreSPI version 4.2.xxx It is not compatible
+ * with CoreSPI version 3.0.xxx.
+ *
+ * The Core SPI driver supports two classes of data transfer operation:
+ * SPI frame operation or SPI block transfer operations.
+ *
+ * Frame operations allow transferring individual SPI frames from 4 to 32-bits
+ * in length. Block operations allow transferring blocks of data organized as
+ * 8-bit frames.
+ *
+ * @file core_spi.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI prototypes
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage Core SPI Bare Metal Driver.
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ CoreSPI is an IP component that implements a full-duplex, synchronous, and
+ configurable serial peripheral interface (SPI) with frame sizes from 4 to 32
+ bits and bus interface sizes of 8-, 16-, or 32-bit. Each CoreSPI instance
+ communicates with up to eight slave devices.
+
+ This driver provides a set of functions for controlling CoreSPI as part of
+ the bare metal system where no operating system is available. These drivers
+ can be adapted to be used as a part of an operating system, but the
+ implementation of the adaptation layer between driver and the operating
+ system's driver model is outside the scope of this User's Guide.
+
+ ==============================================================================
+ Driver Configuration
+ ==============================================================================
+ Your application software should configure the CoreSPI driver through calls
+ to the SPI_init() function for each CoreSPI instance in the hardware design.
+ This function configures a default set of parameters that include a CoreSPI
+ hardware instance base address and the depth of the FIFOs for this instance.
+
+ The CoreSPI instance is configured at the time of instantiation in hardware
+ design for APB width, frame size, FIFO depth, serial clock speed, serial
+ clock polarity, serial clock phase, and slave select state parameters.
+
+ CoreSPI can communicate with up to eight different slave devices that match
+ the CoreSPI configuration at the time of hardware instantiation.
+
+ The functions SPI_configure_slave_mode() and SPI_configure_master_mode() are
+ used to configure the CoreSPI instance as a master or slave as required by
+ the application.
+
+ When CoreSPI wishes to communicate with a specific slave device, call
+ the SPI_set_slave_select() function with the slave number as an argument.
+ This function selects the slave device. A previously selected slave gets
+ unselected by calling the SPI_clear_slave_select() function.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The CoreSPI driver functions are grouped into the following categories:
+ • Initialization
+ • Configuration for either master or slave operations
+ • SPI master frame transfer control
+ • SPI master block transfer control
+ • SPI slave frame transfer control
+ • SPI slave block transfer control
+
+ Frame transfers allow CoreSPI to write or read up to 32-bits of data in a
+ single SPI transaction. For example, a frame transfer of 12-bits might be used
+ to read the result of an ADC conversion from a SPI analog to digital converter.
+
+ Block transfers allow CoreSPI to write and/or read a number of bytes in a single
+ SPI transaction. With the driver as is, block transfer transactions allow data
+ transfers in multiples of 8-bits (8, 16, 24, 32, 40,...) and the CoreSPI instance
+ has to be configured for 8-bit frames. For other frame sizes, the
+ SPI_transfer_block() code can act as a template for developing a frame block
+ transfer function.
+ Block transfers are typically used with byte oriented devices like SPI
+ FLASH devices.
+
+ Note: The CoreSPI instance in the hardware design must be configured for
+ the frame size required by the application; configuration by driver is
+ not possible.
+
+ --------------------------------
+ Initialization
+ --------------------------------
+ The CoreSPI driver is initialized through a call to the SPI_init() function.
+ The SPI_init() function takes a pointer to the global CoreSPI instance data
+ structure of type spi_instance_t and the base address of the CoreSPI instance
+ as defined by the hardware design. The CoreSPI instance global data structure
+ is used by the driver to store state information for each CoreSPI instance.
+ A pointer to these data structures is also used as the first parameter to
+ any of the driver functions to identify which CoreSPI will be used by the
+ called function. It is the responsibility of the application programmer to
+ create and maintain these global CoreSPI instance data structures. Any call
+ to a CoreSPI driver function should be of the form SPI_function_name
+ ( &g_core_spi0, ... ).
+ The SPI_init() function resets the transmit and receives FIFOs of CoreSPI
+ instance being initialized.
+ The SPI_init() function must be called before any other CoreSPI driver
+ functions can be called.
+
+ ----------------------------------------------------
+ Configuration
+ ----------------------------------------------------
+ A CoreSPI instance can operate either as a master or as a slave SPI device.
+ There are two distinct functions for configuring a CoreSPI instance for
+ master or slave operations.
+
+ ## Master Configuration
+ The SPI_configure_master_mode() function configures the specified CoreSPI
+ block for operations as an SPI master. This function must be called once
+ before the CoreSPI block communicates with an SPI slave device.
+
+ ## Slave Configuration
+ The SPI_configure_slave_mode() function configures the specified CoreSPI
+ block for operations as a SPI slave. This function must be called after
+ calling the SPI_init() to configure the CoreSPI instance referred by this_spi
+ parameter to operate in the slave mode.
+
+ -------------------------------------
+ SPI Master Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master frame transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_frame()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves to be addressed by
+ calling the SPI_set_slave_select() function. This causes the relevant select
+ line(s) to become asserted while data is clocked out onto the SPI data line.
+
+ A function call is then made to SPI_transfer_frame() specifying the value
+ of the data frame to be sent and returning the value read.
+
+ After the transfer is complete, use the SPI_clear_slave_select() function
+ to prevent this slave select line from being asserted during subsequent SPI
+ transactions. A call to this function is required only if the master is
+ communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Master Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI master block transfers:
+ • SPI_set_slave_select()
+ • SPI_transfer_block()
+ • SPI_clear_slave_select()
+
+ The master must first select the target slave or slaves by calling
+ SPI_set_slave_select(). This causes the relevant slave select line(s) to
+ become asserted while data is clocked out onto the SPI data line.
+ Alternatively, a general purpose input/output (GPIO) can be used to control
+ the state of the target slave device's chip select signal.
+
+ A call is then made to the SPI_transfer_block() function. The parameters of
+ this function specify the following:
+ • The number of bytes to be transmitted
+ • A pointer to the buffer containing the data to be transmitted
+ • The number of bytes to be received
+ • A pointer to the buffer where the received data gets stored
+
+ The number of bytes to be transmitted can be set to zero to indicate that the
+ transfer is purely a block read transfer. The number of bytes to be received
+ can be set to zero to specify that the transfer is purely a block write
+ transfer.
+
+ Block mode transfers as implemented by the driver are effectively half duplex
+ as we do not store the values received from the slave device whilst we are
+ transmitting. If full duplex operation is required, the driver
+ SPI_transfer_block() function can serve as a starting point for implementing
+ full duplex block transfers.
+
+ The SPI_clear_slave_select() function can be used after the transfer is
+ complete to prevent this slave select line from being asserted during
+ subsequent SPI transactions. A call to this function is only required if
+ the master is communicating with multiple slave devices.
+
+ -------------------------------------
+ SPI Slave Frame Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave frame transfers:
+ • SPI_set_frame_rx_handler()
+ • SPI_set_slave_tx_frame()
+
+ The SPI_set_frame_rx_handler() function specifies the receive handler
+ function that is called when a frame of data has been received by the
+ SPI when it is configured as a slave. The receive handler function specified
+ through this call processes the frame data written over the SPI bus to the
+ SPI slave by the remote SPI master. The receive handler function must be
+ implemented as part of the application. It is only required if the SPI slave
+ is the target of SPI frame write transactions.
+
+ The SPI_set_slave_tx_frame() function specifies the frame data that is
+ returned to the SPI master. The frame data specified through this function
+ is the value that will be read over the SPI bus by the remote SPI master,
+ when it initiates a transaction. Call the SPI_set_slave_tx_frame() function
+ only if the SPI slave is the target of SPI read transactions. That is, if
+ data is meant to be read over CoreSPI.
+
+ If both frame handlers are required, call the SPI_set_frame_rx_handler()
+ first, otherwise the initial TX frame gets discarded when SPI_set_frame_rx_handler()
+ clears the FIFOs as part of its initialization.
+
+ -------------------------------------
+ SPI Slave Block Transfer Control
+ -------------------------------------
+ The following functions are used as a part of the SPI slave block transfers:
+ • SPI_set_slave_block_buffers()
+ • SPI_set_cmd_handler()
+ • SPI_set_cmd_response()
+
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies the following:
+ • The buffer containing the data that will be returned to the remote SPI
+ master
+ • The buffer where data received from the remote SPI master will be
+ stored
+ • The optional handler function that will be called after the receive
+ buffer is filled
+
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ is called by the driver once a specific number of frames have been
+ received after the SPI chip select signal becomes active. The number of
+ bytes making up the command part of the transaction is specified as part of
+ the parameters to the SPI_set_cmd_handler() function. The command handler
+ function is implemented as a part of the application making use of the SPI
+ driver and typically calls the SPI_set_cmd_response() function.
+
+ The SPI_set_cmd_response() function specifies the data that gets returned
+ to the master. Typically, the SPI_set_slave_block_buffers() function is
+ called as a part of the system initialisation to specify the data sent to
+ the master while the command bytes are being received. The transmit buffer
+ specified through calling the SPI_set_slave_block_buffers() function would
+ also typically include one or more bytes allowing the turn around time
+ for the command handler function to execute and call the
+ SPI_set_cmd_response() function.
+
+ *//*=========================================================================*/
+#ifndef CORE_SPI_H_
+#define CORE_SPI_H_
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SPI FIFO Depth
+ =======================================
+ SPI_MAX_FIFO_DEPTH & SPI_MIN_FIFO_DEPTH constants define the maximum and minimum
+ FIFO depths allowed for the CoreSPI instance. User need to inform the driver of
+ the FIFO depth for each CoreSPI instance to ensure that the FIFOs are managed correctly.
+
+ | Constant | Description |
+ |--------------------|----------------------------------------------------|
+ | SPI_MAX_FIFO_DEPTH | Maximum FIFO depth allowed for the CoreSPI instance|
+ | SPI_MIN_FIFO_DEPTH | Minimum FIFO depth allowed for the CoreSPI instance|
+
+ */
+#define SPI_MAX_FIFO_DEPTH 32u
+#define SPI_MIN_FIFO_DEPTH 1u
+
+/***************************************************************************//**
+ Instances of this structure are used to identify the specific CoreSPI hardware
+ instances. A pointer to an instance of the spi_instance_t structure is passed
+ as the first parameter to the CoreSPI driver functions to identify which SPI
+ performs the requested operation.
+ */
+typedef struct spi_instance spi_instance_t;
+
+/***************************************************************************//**
+ This function pointer type is to assign a callback function for TX interrupt
+ when slave wants to send the next updated frame.
+
+ Declaring and Implementing Slave Frame Transmit Handler Functions:
+ Slave transmit frame update handler functions should follow the following
+ prototype:
+ void slave_tx_frame_update_handler ( spi_instance_t * this_spi );
+ The actual name of the transmit handler is unimportant. You can use any name
+ of your choice for the frame update handler.
+
+ A common handler function may be used when multiple CoreSPI instances are
+ configured as slave, as the particular slave device currently requiring
+ service is indicated by the function parameter.
+ */
+typedef void (*spi_slave_frame_tx_handler_t)( spi_instance_t * this_spi );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by the SPI slave
+ frame receive handler functions. These functions are registered with the SPI
+ driver through the SPI_set_frame_rx_handler() function.
+
+ Declaring and Implementing the Slave Frame Receive Handler Functions:
+ The Slave frame receive handler functions should follow the following
+ prototype:
+ void slave_frame_receive_handler(uint32_t rx_frame);
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_frame parameter contains
+ the value of the received frame.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+ This defines the function prototype that must be followed by SPI slave
+ block receive handler functions. These functions are registered with the
+ SPI driver through the SPI_set_slave_block_buffers() function.
+
+ Declaring and Implementing Slave Block Receive Handler Functions:
+ Slave block receive handler functions should follow the following prototype:
+ void spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+ The actual name of the receive handler is unimportant. You can use any name
+ of your choice for the receive frame handler. The rx_buff parameter contains
+ a pointer to the start of the received block. The rx_size parameter contains
+ the number of bytes of the received block.
+
+ Separate handler functions are required for each slave instance as there is
+ no indication of the slave requiring service passed to the handler.
+
+ */
+typedef void (*spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the SPI_configure_master_mode(), SPI_set_slave_select(),
+ and SPI_clear_slave_select() functions.
+ */
+typedef enum __spi_slave_t
+{
+ SPI_SLAVE_0 = 0,
+ SPI_SLAVE_1 = 1,
+ SPI_SLAVE_2 = 2,
+ SPI_SLAVE_3 = 3,
+ SPI_SLAVE_4 = 4,
+ SPI_SLAVE_5 = 5,
+ SPI_SLAVE_6 = 6,
+ SPI_SLAVE_7 = 7,
+ SPI_MAX_NB_OF_SLAVES = 8
+} spi_slave_t;
+
+/***************************************************************************//**
+ This enumeration is used to indicate the current slave mode transfer type so
+ that we are not relying on buffer comparisons to dictate the logic of the driver.
+ */
+typedef enum __spi_sxfer_mode_t
+{
+ SPI_SLAVE_XFER_NONE = 0, /* Not configured yet */
+ SPI_SLAVE_XFER_BLOCK = 1, /* Block transfers, with SSEND delimiting end of block */
+ SPI_SLAVE_XFER_FRAME = 2 /* Single frame transfers */
+} spi_sxfer_mode_t;
+
+/***************************************************************************//**
+ There is one instance of this structure for each of the core SPIs. Instances
+ of this structure are used to identify a specific SPI. A pointer to an
+ instance of the spi_instance_t structure is passed as the first parameter to
+ SPI driver functions to identify which SPI should perform the requested operation.
+ */
+struct spi_instance{
+
+ /* Base address in the processor's memory map for the
+ registers of the CoreSPI instance being initialized */
+ addr_t base_addr; /* Base address of SPI hardware instance */
+
+ uint32_t rx_frame; /* received data */
+
+ /* Internal transmit state: */
+ const uint8_t * slave_tx_buffer; /* Pointer to slave transmit buffer */
+ uint32_t slave_tx_size; /* Size of slave transmit buffer */
+ uint32_t slave_tx_idx; /* Current index into slave transmit buffer */
+
+ /* Slave command response buffer: */
+ const uint8_t * resp_tx_buffer;
+ uint32_t resp_buff_size;
+ uint32_t resp_buff_tx_idx;
+ spi_block_rx_handler_t cmd_handler;
+ uint32_t cmd_done; /* Flag which indicates response has been set up and
+ it is safe to pad with 0s once the response is sent */
+
+ /* Internal receive state: */
+ uint8_t * slave_rx_buffer; /* Pointer to buffer where data received by a slave will be stored */
+ uint32_t slave_rx_size; /* Slave receive buffer size */
+ uint32_t slave_rx_idx; /* Current index into slave receive buffer */
+
+ /* Slave received frame handler: */
+ spi_frame_rx_handler_t frame_rx_handler; /* Pointer to function that will be called when a frame
+ is received when the SPI block is configured as slave */
+ /* Slave transmitted frame handler: */
+ uint32_t slave_tx_frame; /* Value of the data frame that will be transmitted
+ when the SPI block is configured as slave */
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler; /* Callback function pointer to update slave_tx_frame */
+
+ /* Slave block rx handler: */
+ spi_block_rx_handler_t block_rx_handler; /* Pointer to the function that will be called when a data block has been received */
+
+ /* Per instance specific hardware information that the driver needs to know */
+ uint16_t fifo_depth; /* Depth of RX and TX FIFOs in frames */
+
+ /* How we are expecting to deal with slave transfers */
+ spi_sxfer_mode_t slave_xfer_mode; /* Current slave mode transfer configuration */
+};
+
+/*------------------------Public Function-------------------------------------*/
+
+/***************************************************************************//**
+ The SPI_init() function initializes the hardware and data structures of a
+ CoreSPI instance referenced by this_spi parameter. This function must be
+ called for each CoreSPI instance with a unique this_spi and base_addr
+ parameter combination. The SPI_init() function must be called before any
+ other CoreSPI driver functions are called.
+
+ After calling the SPI_init() the CoreSPI is configured as a master,
+ all interrupt sources will be masked and all the slaves are deselected.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be initialized. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the CoreSPI instance being initialized. It is assumed that
+ any non NULL value passed in here points to a valid instance of a CoreSPI as
+ the driver has no way of verifying this. Failure to pass in a valid address
+ can result in system instability.
+
+ @param fifo_depth
+ The fifo_depth parameter specifies the number of frames in the receive
+ and transmit FIFOs of the CoreSPI instance being initialized.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ @endcode
+ */
+void SPI_init
+(
+ spi_instance_t * this_spi,
+ addr_t base_addr,
+ uint16_t fifo_depth
+);
+
+/***************************************************************************//**
+ The SPI_configure_slave_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_slave_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_configure_master_mode() function is used when a CoreSPI instance is
+ to be configured as a SPI master.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to be configured. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+
+ int main(void)
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_master_mode ( &g _spi0 );
+ }
+ @endcode
+ */
+void SPI_configure_master_mode
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_select() function is used by a CoreSPI master to select a
+ specific slave. This function causes the relevant slave select signal to be
+ asserted while data is clocked out onto the SPI data line.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+
+ @endcode
+ */
+void SPI_set_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_clear_slave_select() function is used by a CoreSPI master to
+ deselect a specific slave. This function causes the relevant slave select
+ signal to be de-asserted.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param slave
+ The slave parameter is one of the spi_slave_t enumerated constants
+ identifying a slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_clear_slave_select
+(
+ spi_instance_t * this_spi,
+ spi_slave_t slave
+);
+
+/***************************************************************************//**
+ The SPI_transfer_frame() function is used by a SPI master to transmit and
+ receive a single frame of the size that has been configured at the time of
+ CoreSPI hardware instantiation. This function is typically used for
+ transactions with a SPI slave where the number of transmit and receive bits
+ are not divisible by 8 or where full duplex exchange of frames is required.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_bits
+ The tx_bits parameter is a 32-bit word containing the value that will be
+ transmitted. If the frame size configured for the CoreSPI is less than 32-bits,
+ the upper bits will be ignored.
+ Note: The bit length of the value to be transmitted to the slave is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @return
+ This function returns a 32-bit word containing the value that is received
+ from the slave. If the frame size configured for the CoreSPI in question is
+ less that 32-bits, the upper bits will be 0.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t master_tx_frame = 0x0100A0E1;
+ uint32_t master_rx;
+
+ SPI_init(&g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 );
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0 );
+ master_rx = SPI_transfer_frame( &g_spi0, master_tx_frame );
+ SPI_clear_slave_select( &g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+uint32_t SPI_transfer_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t tx_bits
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block() function is used by the SPI master to transmit and
+ receive blocks of data organized as a specified number of 8-bit frames. It
+ can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data
+ sent by the master from the beginning of the transfer. This pointer can be
+ null (0) if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes in cmd_buffer that
+ will be sent. A value ‘0’ indicates that no data needs to be sent to the slave.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stored in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_buffer,
+ uint16_t rx_byte_size
+);
+
+/***************************************************************************//**
+ The SPI_transfer_block_store_all_resp() function is used by the SPI master
+ to transmit and receive blocks of data organized as a specified number
+ of 8-bit frames. It can be used for the following:
+ • Writing a data block to a slave
+ • Reading a data block from a slave
+ • Sending a command to a slave followed by reading the outcome of
+ the command in a single SPI transaction
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param cmd_buffer
+ The cmd_buffer parameter is a pointer to the buffer that contains the data sent by
+ the master from the beginning of the transfer. This pointer can be null (0)
+ if the master does not need to send a command before reading data.
+
+ @param cmd_byte_size
+ The cmd_byte_size parameter specifies the number of bytes contained in
+ cmd_buffer that will be sent. A value ‘0’ indicates that no data needs
+ to be sent to the slave.
+
+ @param rx_data_buffer
+ The rx_data_buffer parameter is a pointer to the buffer that stores the data received
+ from the slave after sending the command. This pointer can be null (0) if the
+ master does not receive any data from the slave.
+
+ @param rx_byte_size
+ The rx_byte_size parameter specifies the number of bytes received from
+ the slave and stores in the rx_buffer. A value ‘0’ indicates that no data is
+ to be read from the slave.
+
+ @param cmd_response_buffer
+ The cmd_response_buffer parameter is a pointer to the buffer which stores the
+ command response from the slave, while the master is transmitting the number
+ of bytes indicated by cmd_byte_size parameter.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Polled write transfer example
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+
+ uint8_t master_tx_buffer[MASTER_TX_BUFFER] =
+ {
+ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+ };
+
+ uint8_t cmd_rx_buffer[CMD_RX_BUFFER]={0};
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+
+ SPI_configure_master_mode( &g_spi0 );
+
+ SPI_set_slave_select( &g_spi0, SPI_SLAVE_0) ;
+ SPI_transfer_block_store_all_resp
+ (
+ &g_spi0,
+ master_tx_buffer,
+ sizeof(master_tx_buffer),
+ 0,
+ 0,
+ cmd_response_buffer
+ );
+ SPI_clear_slave_select(&g_spi0, SPI_SLAVE_0 );
+ @endcode
+ */
+void SPI_transfer_block_store_all_resp
+(
+ spi_instance_t * this_spi,
+ const uint8_t * cmd_buffer,
+ uint16_t cmd_byte_size,
+ uint8_t * rx_data_buffer,
+ uint16_t rx_byte_size,
+ uint8_t * cmd_response_buffer
+);
+
+/***************************************************************************//**
+ The SPI_set_frame_rx_handler() function is used by the SPI slaves to specify
+ the receive handler function that is called by the SPI driver interrupt
+ handler when a frame of data is received by the SPI slave.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param rx_handler
+ The rx_handler parameter is a pointer to the frame receive handler that must
+ be called when a frame is received by the CoreSPI slave. Passing in a NULL
+ pointer disables the receive handler but does enable the receive interrupt to
+ ensure the RX FIFO is empty each time a frame is received.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t g_slave_rx_frame = 0;
+ spi_instance_t g_spi0;
+
+ void slave_frame_handler(uint32_t rx_frame)
+ {
+ g_slave_rx_frame = rx_frame;
+ }
+ int setup_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_frame_rx_handler( &g_spi0, slave_frame_handler );
+ }
+ @endcode
+ */
+void SPI_set_frame_rx_handler
+(
+ spi_instance_t * this_spi,
+ spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_tx_frame() function is used by the SPI slaves to specify
+ the frame that gets transmitted when a transaction is initiated by the SPI
+ master. This function allows you to assign a slave_tx_frame_handler function,
+ which will be executed upon transmit interrupt when the SPI is in slave mode.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param frame_value
+ The frame_value parameter contains the value of the frame to be sent to the
+ master.
+ Note: The bit length of the value to be transmitted to the master is
+ set when the CoreSPI is instantiated in the hardware design.
+
+ @param slave_tx_frame_handler
+ The slave_tx_frame_handler function pointer is executed upon occurrence of
+ transmit interrupt when CoreSPI is operating in slave mode. This parameter
+ is optional and if set to NULL it is assumed that the frame value is static or
+ updated asynchronously.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ spi_instance_t g_spi0 ;
+ const uint32_t slave_tx_frame[2] = { 0x0110F761, 0x0110F671 };
+ uint32_t master_rx;
+ uint32_t slave_frame_idx = 0 ;
+
+ slave_frame_update( spi_instance_t * this_spi )
+ {
+ this_spi->slave_tx_frame = slave_tx_frame[slave_frame_idx++];
+ if( slave_frame_idx > 2 )
+ slave_frame_idx = 0;
+ }
+ main()
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 1 );
+ SPI_configure_master_mode( &g_spi0 ) ;
+ SPI_set_slave_tx_frame( &g_spi0, slave_tx_frame[slave_frame_idx++],
+ &slave_frame_update );
+ }
+ @endcode
+ */
+void SPI_set_slave_tx_frame
+(
+ spi_instance_t * this_spi,
+ uint32_t frame_value,
+ spi_slave_frame_tx_handler_t slave_tx_frame_handler
+);
+
+/***************************************************************************//**
+ The SPI_set_slave_block_buffers() function is used to configure an SPI slave
+ for block transfer operations. It specifies one or more of the following:
+ • The data that is transmitted when accessed by a master.
+ • The buffer where the data received from a master is stored.
+ • The handler function that must be called after the receive buffer has
+ been filled.
+ • The number of bytes that must be received from the master before calling
+ the recieve handler function.
+ These parameters allow the following use cases:
+ • Slave performing an action after receiving a block of data from a
+ master containing a command. This action is performed by the
+ receive handler based on the content of the receive data buffer.
+ • Slave returning a block of data to the master. The type of information
+ is always the same but the actual values change over time. For example,
+ returning the voltage of a predefined set of analog inputs.
+ • Slave returning data based on a command contained in the first part of
+ the SPI transaction. For example, reading the voltage of the analog
+ input specified by the first data byte by the master. This is achieved
+ by using the SPI_set_slave_block_buffers() function in conjunction with
+ functions SPI_set_cmd_handler() and SPI_set_cmd_response().
+
+ See the SPI_set_cmd_handler() function description for details of
+ this use case.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data that
+ will be sent to the master. This parameter can be set to ‘0’ if the SPI
+ slave is not intended to be the target of SPI read transactions.
+
+ @param tx_buff_size
+ The tx_buff_size parameter specifies the number of bytes that are
+ transmitted by the SPI slave. It is the number of bytes contained in the
+ tx_buffer. This parameter can be set to ‘0’ if the SPI slave is not
+ intended to be the target of SPI read transactions. The driver returns 0s
+ to the master if there is no buffer specified or the master reads beyond the
+ end of the buffer.
+ Note: If SPI_transfer_block() is used to read from this slave and there is
+ no command handler involved, the buffer size here must be at least the
+ combined length of the command and response specified by the master.
+ On receiving this data, the master discards the data bytes equal to
+ command length bytes from the start of the received buffer.
+
+ @param rx_buffer
+ The rx_buffer parameter is a pointer to the buffer where data received
+ from the master is stored. This parameter can be set to ‘0’ if the
+ SPI slave is not intended to be the target of SPI write or write-read
+ transactions.
+
+ @param rx_buff_size
+ The rx_buff_size parameter specifies the size of the receive buffer. It is
+ also the number of bytes that must be received before the receive handler
+ is called, if a receive handler is specified using the block_rx_handler
+ parameter. Any bytes received in excess of the size specified by the
+ rx_buff_size parameter are discarded. This parameter can be set to ‘0’
+ if the SPI slave is not intended to be the target of SPI write or
+ write-read transactions.
+
+ @param block_rx_handler
+ The block_rx_handler parameter is a pointer to a function that is called
+ when receive buffer has been filled or the slave select has been de-asserted.
+ This parameter can be set to ‘0’ if the SPI slave is not intended to be the
+ target of SPI write or write-read transactions.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ Slave Performing Operation Based on Master Command:
+ In this example the SPI slave is configured to receive 10 bytes of data
+ or command from the SPI slave, and process the data received from the master.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+
+ uint32_t nb_of_rx_handler_calls = 0;
+ spi_instance_t g_spi0;
+
+ void spi1_block_rx_handler_b
+ (
+ uint8_t * rx_buff,
+ uint16_t rx_size
+ )
+ {
+ ++nb_of_rx_handler_calls;
+ }
+
+ void setup_slave( void )
+ {
+ uint8_t slave_rx_buffer[10] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ 0,
+ 0,
+ slave_rx_buffer,
+ sizeof( master_tx_buffer ),
+ spi1_block_rx_handler_b
+ );
+ }
+ @endcode
+ */
+void SPI_set_slave_block_buffers
+(
+ spi_instance_t * this_spi,
+ const uint8_t * tx_buffer,
+ uint32_t tx_buff_size,
+ uint8_t * rx_buffer,
+ uint32_t rx_buff_size,
+ spi_block_rx_handler_t block_rx_handler
+);
+
+/***************************************************************************//**
+ The SPI_isr() function is the top level interrupt handler function for the
+ CoreSPI driver. You must call SPI_isr() from the system level
+ (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ triggered by the CoreSPI SPIINT signal. Your system level interrupt handler
+ must also clear the system level interrupt triggered by the CoreSPI SPIINT
+ signal before returning, to prevent a re-assertion of the same interrupt.
+
+ This function supports all types of interrupt triggered by CoreSPI. It is not
+ a complete interrupt handler by itself; rather, it is a top level wrapper that
+ abstracts CoreSPI command interrupt and slave mode transmit interrupt handling
+ by calling lower level handler functions specific to each type of CoreSPI
+ interrupt. You must create the lower level handler functions to suit your
+ application and register them with the driver through calling the
+ SPI_set_cmd_handler(), SPI_set_cmd_response(), and SPI_set_slave_tx_frame()
+ functions.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+
+ Example of configuring a CoreInterrupt connected to the Fabric Interrupt on a
+ SmartFusion device to handle CoreSPI interrupt.
+
+ #define #define SPI1_INT_IRQ_NB 0
+ spi_instance_t g_spi0;
+
+ Void CIC_irq1_handler(void)
+ {
+ SPI_isr( &g_spi0 );
+ }
+
+ void Fabric_IRQHandler( void )
+ {
+ // Call the CoreInterrupt driver ISR to determine the source of the
+ // interrupt and call the relevant ISR registered to it.
+ CIC_irq_handler();
+
+ // Clear NVIC interrupt status to allow further interrupts
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ }
+
+ main()
+ {
+ ...
+
+ CIC_init( CIC_BASE_ADDR );
+
+ // Install handler for SPI IRQ
+ CIC_set_irq_handler( SPI0_INT_IRQ_NB, CIC_irq1_handler );
+
+ NVIC_ClearPendingIRQ( Fabric_IRQn );
+ NVIC_EnableIRQ( Fabric_IRQn );
+
+ CIC_enable_irq( SPI1_INT_IRQ_NB );
+
+ ...
+ }
+ @endcode
+ */
+void SPI_isr
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_handler() function specifies a command handler function that
+ will be called when the number of bytes received reaches the command size
+ specified as cmd_size parameter.
+
+ This function is used by the SPI slaves performing block transfers. Its
+ purpose is to allow an SPI slave to decide the data that will be returned to
+ the master while an SPI transaction is taking place. Typically, one or more
+ command bytes are sent by the master to request some specific data. The slave
+ interprets the command byte(s) while one or more turn-around bytes are
+ transmitted. The slave adjusts its transmit data buffer based on the command
+ during the turn around time.
+
+ The following table provides an example of the use of this function where the
+ SPI slave returns data bytes D0 to D6 based on the value of a command. The
+ 3 bytes long command is made up of a command opcode byte followed by an
+ address byte followed by a size byte. The cmd_handler() function specified
+ through an earlier call to SPI_set_cmd_handler() is called by the CoreSPI
+ driver once the third byte is received. The cmd_handler() function
+ interprets the command bytes and calls SPI_set_cmd_response() to set the SPI
+ slave's response transmit buffer with the data to be transmitted after the
+ turnaround bytes (T0 to T3). The number of turnaround bytes must be
+ sufficient to give enough time for the cmd_handler() to execute. The number
+ of turnaround bytes is specified by the protocol used on top of the SPI
+ transport layer so that master and slave agree on the number of turn around
+ bytes.
+
+|Timestamp| SPI Transaction | Bytes | Comments |
+|---------|-------------|----------------------|---------------|
+| t0|COMMAND|C A S |C - command opcode byte, A - address byte, S - size byte|
+|t1| TURN-AROUND|T0 T1 |cmd_handler() called here (T0 to T3 are TURN-AROUND bytes)|
+|t2|TURN-AROUND|T2 T3|SPI_set_cmd_response() called here by implementation of cmd_handler()
+|| | |to set the data that will be transmitted by the SPI slave.|
+|t3| DATA | D0 D1 D2 D3 D4 D5 D6 |Data transmition (SPI slave return data bytes)|
+
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure identifying
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @param cmd_handler
+ The cmd_handler parameter is a pointer to a function with the prototype:
+ void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+ It specifies the function that will be called when the number of bytes
+ specified by the cmd_size parameter has been received.
+
+ @param cmd_size
+ The cmd_size parameter specifies the number of bytes that must be received
+ before calling the command handler function specified by the cmd_handler.
+ The CoreSPI supports cmd_size values in the range 1 to 7.
+
+ @return
+ This function does not return any value.
+
+ @example
+ @code
+ The following example demonstrates how to configure CoreSPI to implement
+ the protocol given as an example above. The configure_slave() function
+ configures CoreSPI. It sets receive and transmit buffers. The transmit
+ buffer specified through the call to SPI_set_slave_block_buffers() function
+ specifies the data that will be returned to the master in bytes between
+ t0 and t3. These bytes will be sent to the master while the master transmits
+ the command and dummy bytes. The spi_slave_cmd_handler() function will be
+ called by the driver at time t1 after the 3 command bytes have been received.
+ The spi_block_rx_handler() function will be called by the driver at time t4,
+ when the transaction completes and the slave select signal becomes
+ de-asserted.
+
+ #define SPI0_BASE_ADDR 0xC2000000
+ #define COMMAND_SIZE 3
+ #define NB_OF_DUMMY_BYTES 4
+ #define MAX_TRANSACTION_SIZE 16
+
+ spi_instance_t g_spi0;
+ uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+ uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+
+ void configure_slave( void )
+ {
+ SPI_init( &g_spi0, SPI0_BASE_ADDR, 8 );
+ SPI_configure_slave_mode( &g_spi0 );
+ SPI_set_slave_block_buffers
+ (
+ &g_spi0,
+ slave_tx_buffer,
+ COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+ slave_rx_buffer,
+ sizeof(slave_rx_buffer),
+ spi_block_rx_handler
+ );
+
+ SPI_set_cmd_handler
+ (
+ &g_spi0,
+ spi_slave_cmd_handler,
+ COMMAND_SIZE
+ );
+ }
+
+ void spi_slave_cmd_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ uint8_t command;
+ uint8_t address;
+ uint8_t size;
+ uint8_t * p_response;
+ uint32_t response_size;
+
+ command = rx_buff[0];
+ address = rx_buff[1];
+ size = rx_buff[2];
+
+ p_response = get_response_data( command, address, size, &response_size );
+ SPI_set_cmd_response( &g_spi0, p_response, response_size );
+ }
+
+ void spi_block_rx_handler
+ (
+ uint8_t * rx_buff,
+ uint32_t rx_size
+ )
+ {
+ process_rx_data( rx_buff, rx_size );
+ }
+ @endcode
+ */
+void SPI_set_cmd_handler
+(
+ spi_instance_t * this_spi,
+ spi_block_rx_handler_t cmd_handler,
+ uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The SPI_set_cmd_response() function specifies the data that will be returned
+ to the master. See the description of SPI_set_cmd_handler() for details.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ a g_core_spi global data structure defined within the application code.
+
+ @param resp_tx_buffer
+ The resp_tx_buffer parameter is a pointer to the buffer containing the data
+ that must be returned to the host in the data phase of an SPI transaction.
+
+ @param resp_buff_size
+ The resp_buff_size parameter specifies the size of the buffer pointed by the
+ resp_tx_buffer parameter.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_set_cmd_response
+(
+ spi_instance_t * this_spi,
+ const uint8_t * resp_tx_buffer,
+ uint32_t resp_buff_size
+);
+
+/***************************************************************************//**
+ The SPI_enable() function enables the CoreSPI and allows it to respond to the external
+ signals. It is usually called to re-enable a CoreSPI instance which has been
+ disabled previously via by calling the SPI_disable() as the normal state of a CoreSPI
+ after enabling the initialization.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_enable
+(
+ spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+ The SPI_disable() function disables the CoreSPI and stops responding to the
+ external signals.
+
+ @param this_spi
+ The this_spi parameter is a pointer to a spi_instance_t structure that identifies
+ the CoreSPI hardware block to operate on. This parameter must point to
+ the g_core_spi global data structure defined within the application code.
+
+ @return
+ This function does not return any value.
+ */
+void SPI_disable
+(
+ spi_instance_t * this_spi
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_SPI_H_*/
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
new file mode 100644
index 0000000..a3e5b2a
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSPI/corespi_regs.h
@@ -0,0 +1,270 @@
+/***************************************************************************//**
+ * Copyright 2011-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file corespi_regs.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief CoreSPI memory map
+ *
+ */
+
+#ifndef CORESPI_REGS_H_
+#define CORESPI_REGS_H_
+
+/*******************************************************************************
+ * Control register 1:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL1_REG_OFFSET 0x00u
+
+#define CTRL1_ENABLE_OFFSET 0x00u
+#define CTRL1_ENABLE_MASK 0x01u
+#define CTRL1_ENABLE_SHIFT 0x00
+
+#define CTRL1_MASTER_OFFSET 0x00u
+#define CTRL1_MASTER_MASK 0x02u
+#define CTRL1_MASTER_SHIFT 0x01
+
+#define CTRL1_INTRXDATA_OFFSET 0x00u
+#define CTRL1_INTRXDATA_MASK 0x04u
+#define CTRL1_INTRXDATA_SHIFT 0x02
+
+#define CTRL1_INTTXDONE_OFFSET 0x00u
+#define CTRL1_INTTXDONE_MASK 0x08u
+#define CTRL1_INTTXDONE_SHIFT 0x03
+
+#define CTRL1_INTRXOVFLOW_OFFSET 0x00u
+#define CTRL1_INTRXOVFLOW_MASK 0x10u
+#define CTRL1_INTRXOVFLOW_SHIFT 0x04
+
+#define CTRL1_INTTXURUN_OFFSET 0x00u
+#define CTRL1_INTTXURUN_MASK 0x20u
+#define CTRL1_INTTXURUN_SHIFT 0x05
+
+#define CTRL1_FRAMEURUN_OFFSET 0x00u
+#define CTRL1_FRAMEURUN_MASK 0x40u
+#define CTRL1_FRAMEURUN_SHIFT 0x06
+
+#define CTRL1_OENOFF_OFFSET 0x00u
+#define CTRL1_OENOFF_MASK 0x80u
+#define CTRL1_OENOFF_SHIFT 0x07
+
+/*******************************************************************************
+ * Interrupt clear register:
+ *------------------------------------------------------------------------------
+ */
+#define INTCLR_REG_OFFSET 0x04u
+
+#define INTCLR_TXDONE_OFFSET 0x04u
+#define INTCLR_TXDONE_MASK 0x01u
+#define INTCLR_TXDONE_SHIFT 0x00
+
+#define INTCLR_RXDONE_OFFSET 0x04u
+#define INTCLR_RXDONE_MASK 0x02u
+#define INTCLR_RXDONE_SHIFT 0x01
+
+#define INTCLR_RXOVERFLOW_OFFSET 0x04u
+#define INTCLR_RXOVERFLOW_MASK 0x04u
+#define INTCLR_RXOVERFLOW_SHIFT 0x02
+
+#define INTCLR_TXUNDERRUN_OFFSET 0x04u
+#define INTCLR_TXUNDERRUN_MASK 0x08u
+#define INTCLR_TXUNDERRUN_SHIFT 0x03
+
+#define INTCLR_CMDINT_OFFSET 0x04u
+#define INTCLR_CMDINT_MASK 0x10u
+#define INTCLR_CMDINT_SHIFT 0x04
+
+#define INTCLR_SSEND_OFFSET 0x04u
+#define INTCLR_SSEND_MASK 0x20u
+#define INTCLR_SSEND_SHIFT 0x05
+
+#define INTCLR_RXDATA_OFFSET 0x04u
+#define INTCLR_RXDATA_MASK 0x40u
+#define INTCLR_RXDATA_SHIFT 0x06
+
+#define INTCLR_TXDATA_OFFSET 0x04u
+#define INTCLR_TXDATA_MASK 0x80u
+#define INTCLR_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Receive data register:
+ *------------------------------------------------------------------------------
+ */
+#define RXDATA_REG_OFFSET 0x08u
+
+/*******************************************************************************
+ * Transmit data register:
+ *------------------------------------------------------------------------------
+ */
+#define TXDATA_REG_OFFSET 0x0Cu
+
+/*******************************************************************************
+ * Masked interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTMASK_REG_OFFSET 0x10u
+
+#define INTMASK_TXDONE_OFFSET 0x10u
+#define INTMASK_TXDONE_MASK 0x01u
+#define INTMASK_TXDONE_SHIFT 0x00
+
+#define INTMASK_RXDONE_OFFSET 0x10u
+#define INTMASK_RXDONE_MASK 0x02u
+#define INTMASK_RXDONE_SHIFT 0x01
+
+#define INTMASK_RXOVERFLOW_OFFSET 0x10u
+#define INTMASK_RXOVERFLOW_MASK 0x04u
+#define INTMASK_RXOVERFLOW_SHIFT 0x02
+
+#define INTMASK_TXUNDERRUN_OFFSET 0x10u
+#define INTMASK_TXUNDERRUN_MASK 0x08u
+#define INTMASK_TXUNDERRUN_SHIFT 0x03
+
+#define INTMASK_CMDINT_OFFSET 0x10u
+#define INTMASK_CMDINT_MASK 0x10u
+#define INTMASK_CMDINT_SHIFT 0x04
+
+#define INTMASK_SSEND_OFFSET 0x10u
+#define INTMASK_SSEND_MASK 0x20u
+#define INTMASK_SSEND_SHIFT 0x05
+
+#define INTMASK_RXDATA_OFFSET 0x10u
+#define INTMASK_RXDATA_MASK 0x40u
+#define INTMASK_RXDATA_SHIFT 0x06
+
+#define INTMASK_TXDATA_OFFSET 0x10u
+#define INTMASK_TXDATA_MASK 0x80u
+#define INTMASK_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Raw interrupt status register:
+ *------------------------------------------------------------------------------
+ */
+#define INTRAW_REG_OFFSET 0x14u
+
+#define INTRAW_TXDONE_OFFSET 0x14u
+#define INTRAW_TXDONE_MASK 0x01u
+#define INTRAW_TXDONE_SHIFT 0x00
+
+#define INTRAW_RXDONE_OFFSET 0x14u
+#define INTRAW_RXDONE_MASK 0x02u
+#define INTRAW_RXDONE_SHIFT 0x01
+
+#define INTRAW_RXOVERFLOW_OFFSET 0x14u
+#define INTRAW_RXOVERFLOW_MASK 0x04u
+#define INTRAW_RXOVERFLOW_SHIFT 0x02
+
+#define INTRAW_TXUNDERRUN_OFFSET 0x14u
+#define INTRAW_TXUNDERRUN_MASK 0x08u
+#define INTRAW_TXUNDERRUN_SHIFT 0x03
+
+#define INTRAW_CMDINT_OFFSET 0x14u
+#define INTRAW_CMDINT_MASK 0x10u
+#define INTRAW_CMDINT_SHIFT 0x04
+
+#define INTRAW_SSEND_OFFSET 0x14u
+#define INTRAW_SSEND_MASK 0x20u
+#define INTRAW_SSEND_SHIFT 0x05
+
+#define INTRAW_RXDATA_OFFSET 0x14u
+#define INTRAW_RXDATA_MASK 0x40u
+#define INTRAW_RXDATA_SHIFT 0x06
+
+#define INTRAW_TXDATA_OFFSET 0x14u
+#define INTRAW_TXDATA_MASK 0x80u
+#define INTRAW_TXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Control register 2:
+ *------------------------------------------------------------------------------
+ */
+#define CTRL2_REG_OFFSET 0x18u
+
+#define CTRL2_CMDSIZE_OFFSET 0x18u
+#define CTRL2_CMDSIZE_MASK 0x07u
+#define CTRL2_CMDSIZE_SHIFT 0x00
+
+#define CTRL2_INTCMD_OFFSET 0x18u
+#define CTRL2_INTCMD_MASK 0x10u
+#define CTRL2_INTCMD_SHIFT 0x04
+
+#define CTRL2_INTSSEND_OFFSET 0x18u
+#define CTRL2_INTSSEND_MASK 0x20u
+#define CTRL2_INTSSEND_SHIFT 0x05
+
+#define CTRL2_INTRXDATA_OFFSET 0x18u
+#define CTRL2_INTRXDATA_MASK 0x40u
+#define CTRL2_INTRXDATA_SHIFT 0x06
+
+#define CTRL2_INTTXDATA_OFFSET 0x18u
+#define CTRL2_INTTXDATA_MASK 0x80u
+#define CTRL2_INTTXDATA_SHIFT 0x07
+
+/*******************************************************************************
+ * Command register:
+ *------------------------------------------------------------------------------
+ */
+#define CMD_REG_OFFSET 0x1Cu
+
+#define CMD_RXFIFORST_OFFSET 0x1Cu
+#define CMD_RXFIFORST_MASK 0x01u
+#define CMD_RXFIFORST_SHIFT 0x00
+
+#define CMD_TXFIFORST_OFFSET 0x1Cu
+#define CMD_TXFIFORST_MASK 0x02u
+#define CMD_TXFIFORST_SHIFT 0x01
+
+/*******************************************************************************
+ * Status register:
+ *------------------------------------------------------------------------------
+ */
+#define STATUS_REG_OFFSET 0x20u
+
+#define STATUS_FIRSTFRAME_OFFSET 0x20u
+#define STATUS_FIRSTFRAME_MASK 0x01u
+#define STATUS_FIRSTFRAME_SHIFT 0x00
+
+#define STATUS_DONE_OFFSET 0x20u
+#define STATUS_DONE_MASK 0x02u
+#define STATUS_DONE_SHIFT 0x01
+
+#define STATUS_RXEMPTY_OFFSET 0x20u
+#define STATUS_RXEMPTY_MASK 0x04u
+#define STATUS_RXEMPTY_SHIFT 0x02
+
+#define STATUS_TXFULL_OFFSET 0x20u
+#define STATUS_TXFULL_MASK 0x08u
+#define STATUS_TXFULL_SHIFT 0x03
+
+#define STATUS_RXOVFLOW_OFFSET 0x20u
+#define STATUS_RXOVFLOW_MASK 0x10u
+#define STATUS_RXOVFLOW_SHIFT 0x04
+
+#define STATUS_TXUNDERRUN_OFFSET 0x20u
+#define STATUS_TXUNDERRUN_MASK 0x20u
+#define STATUS_TXUNDERRUN_SHIFT 0x05
+
+#define STATUS_SSEL_OFFSET 0x20u
+#define STATUS_SSEL_MASK 0x40u
+#define STATUS_SSEL_SHIFT 0x06
+
+#define STATUS_ACTIVE_OFFSET 0x20u
+#define STATUS_ACTIVE_MASK 0x80u
+#define STATUS_ACTIVE_SHIFT 0x07
+
+/*******************************************************************************
+ * Slave select register:
+ *------------------------------------------------------------------------------
+ */
+#define SSEL_REG_OFFSET 0x24u
+
+/*******************************************************************************
+ * Transmit data last register:
+ *------------------------------------------------------------------------------
+ */
+#define TXLAST_REG_OFFSET 0x28u
+
+
+#endif /*CORESPI_REGS_H_*/
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
new file mode 100644
index 0000000..b8adaed
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.c
@@ -0,0 +1,889 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * PF_System_Services driver implementation. See file "core_syservices_pf.h" for
+ * description of the functions implemented in this file.
+ *
+ */
+
+#include "core_sysservices_pf.h"
+#include "coresysservicespf_regs.h"
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_BUFFER (( uint8_t* ) 0)
+
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+);
+
+uint32_t g_css_pf_base_addr = 0u;
+
+/***************************************************************************//**
+ * SYS_init()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+)
+{
+ g_css_pf_base_addr = base_addr;
+}
+
+/***************************************************************************//**
+ * SYS_get_serial_number()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if (p_serial_number == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(SERIAL_NUMBER_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_serial_number,
+ SERIAL_NUMBER_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_user_code()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_user_code == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(USERCODE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_user_code,
+ USERCODE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_design_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_design_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DESIGN_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_design_info,
+ DESIGN_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_get_device_certificate()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_device_certificate == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(DEVICE_CERTIFICATE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_device_certificate,
+ DEVICE_CERTIFICATE_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_digest()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_digest == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_RESP_LEN,
+ mb_offset,
+ 0u);
+#else
+ status = execute_ss_command(READ_DIGEST_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_digest,
+ READ_DIGEST_MPFS_RESP_LEN,
+ mb_offset,
+ 0u);
+#endif
+ return status;
+
+}
+
+/***************************************************************************//**
+ * SYS_query_security()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t idx = 0u;
+
+ if(p_security_locks == NULL_BUFFER)
+ {
+ return status;
+ }
+
+#ifndef CORESYSSERVICES_MPFS
+ uint8_t buf[12] = {0};
+ /* Actual QUERY_SECURITY_RESP_LEN is 9 or 33 but PF_System_Services core
+ * needs number of words instead of number of bytes to be written to or read
+ * from MailBox */
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 9u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#else
+ uint8_t buf[36] = {0};
+
+ status = execute_ss_command(QUERY_SECURITY_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ buf,
+ (QUERY_SECURITY_MPFS_RESP_LEN + 3u),
+ mb_offset,
+ 0u);
+
+ for (idx = 0u; idx < 33u; idx++)
+ {
+ *(p_security_locks+idx) = buf[idx];
+ }
+
+#endif
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_read_debug_info()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_debug_info == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_DEBUG_INFO_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_debug_info,
+ READ_DEBUG_INFO_RESP_LEN,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+#ifdef CORESYSSERVICES_MPFS
+/***************************************************************************//**
+ * SYS_read_envm_parameter()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if(p_envm_param == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(READ_ENVM_PARAM_REQUEST_CMD,
+ NULL_BUFFER,
+ 0,
+ p_envm_param,
+ READ_ENVM_PARAM_RESP_LEN,
+ mb_offset,
+ 0);
+ return status;
+}
+
+#endif
+
+/***************************************************************************//**
+ * SYS_puf_emulation_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t mb_format[20] = {0x00};
+ uint8_t index = 0u;
+
+ if((p_response == NULL_BUFFER) || (p_challenge == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ /* Frame the data required for mailbox */
+ mb_format[index] = op_type;
+
+ for (index = 4u; index < 20u; index++)
+ {
+ mb_format[index] = p_challenge[index - 4u];
+ }
+
+ status = execute_ss_command(PUF_EMULATION_SERVICE_REQUEST_CMD,
+ mb_format,
+ PUF_EMULATION_SERVICE_CMD_LEN,
+ p_response,
+ PUF_EMULATION_SERVICE_RESP_LEN,
+ mb_offset,
+ 5u); /* mentioning offset to number of words instead of bytes */
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digital_signature_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_hash == NULL_BUFFER) || (p_response == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if (format == DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD)
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+ else
+ {
+ status = execute_ss_command(DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD,
+ p_hash,
+ DIGITAL_SIGNATURE_HASH_LEN,
+ p_response,
+ DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE,
+ mb_offset,
+ 12u); /* mentioning offset to number of words instead of bytes */
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_write()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+)
+{
+ uint8_t frame[256] = {0x00};
+ uint8_t* p_frame = &frame[0];
+ uint16_t index = 0u;
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(snvm_module >= 221u));
+ if (format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_user_key));
+ }
+
+ if ((p_data == NULL_BUFFER) || (snvm_module >= 221))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (p_user_key == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ if ((format != SNVM_NON_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_TEXT_REQUEST_CMD)
+ && (format != SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* Next 3 bytes RESERVED - For alignment */
+
+ /* Copy user key and send the command/data to mailbox. */
+ if ((format == SNVM_AUTHEN_TEXT_REQUEST_CMD) ||
+ (format == SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD))
+ {
+ /* Copy user data */
+ for (index = 0u; index < (AUTHENTICATED_TEXT_DATA_LEN - USER_SECRET_KEY_LEN - 4u); index++)
+ {
+ *p_frame = p_data[index];
+ p_frame++;
+ }
+
+ /* Copy user key */
+ for (index = 0u; index < USER_SECRET_KEY_LEN; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+ else
+ {
+ /* Copy user data */
+ for (index = 0u; index < (NON_AUTHENTICATED_TEXT_DATA_LEN - 4u); index++)
+ {
+ *(p_frame+index) = p_data[index];
+ }
+
+ status = execute_ss_command(format,
+ &frame[0],
+ NON_AUTHENTICATED_TEXT_DATA_LEN,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_secure_nvm_read()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+)
+{
+ /* Frame the message. */
+ uint8_t frame[16] = {0x00u};
+ uint8_t* p_frame = &frame[0u];
+ uint8_t status = SYS_PARAM_ERR;
+ uint8_t response[256] = {0x00u};
+ uint16_t index = 0u;
+
+ HAL_ASSERT(!(NULL_BUFFER == p_data));
+ HAL_ASSERT(!(NULL_BUFFER == p_admin));
+ HAL_ASSERT(!(snvm_module > 221u));
+
+ HAL_ASSERT(data_len == 236u || data_len == 252u);
+
+ if((p_data == NULL_BUFFER) ||
+ (snvm_module >= 221) ||
+ (p_admin == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ *p_frame = snvm_module; /* SNVMADDR - SNVM module */
+
+ p_frame += 4u; /* RESERVED - For alignment */
+
+ /* Copy user key */
+ if (236u == data_len)
+ {
+ HAL_ASSERT(p_user_key != NULL_BUFFER);
+
+ if(p_user_key == NULL_BUFFER)
+ {
+ return status;
+ }
+
+ for (index = 0u; index < 12u; index++)
+ {
+ *p_frame = p_user_key[index];
+ p_frame++;
+ }
+ }
+ else
+ {
+ p_frame += 12u;
+ }
+
+ status = execute_ss_command(SNVM_READ_REQUEST_CMD,
+ &frame[0],
+ 16u,
+ response,
+ (data_len + 4u),
+ mb_offset,
+ 4u); /* mentioning offset to number of words instead of bytes */
+
+ if (SYS_SUCCESS == status)
+ {
+ for (index = 0u; index < 4u; index++)
+ {
+ *(p_admin+index) = (uint32_t)response[index];
+ }
+
+
+ /* Copy data into user buffer. */
+ for (index = 4u; index < (data_len + 4u); index++)
+ {
+ *(p_data + (index - 4u)) = response[index];
+ }
+ }
+ else
+ {
+ ;
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_nonce_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ if((p_nonce == NULL_BUFFER))
+ {
+ return status;
+ }
+
+ status = execute_ss_command(NONCE_SERVICE_REQUEST_CMD,
+ NULL_BUFFER,
+ 0u,
+ p_nonce,
+ NONCE_SERVICE_RESP_LEN,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_bitstream_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_spi_flash_address = spi_flash_address;
+ status = execute_ss_command(BITSTREAM_AUTHENTICATE_CMD,
+ (uint8_t* )&l_spi_flash_address,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_IAP_image_authenticate_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+
+ HAL_ASSERT(!(spi_idx == 1u));
+
+ if (spi_idx == 1u)
+ {
+ return status;
+ }
+
+ status = execute_ss_command(IAP_BITSTREAM_AUTHENTICATE_CMD,
+ NULL_BUFFER,
+ 0u,
+ NULL_BUFFER,
+ 0u,
+ spi_idx,
+ 0u);
+
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_digest_check_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint32_t l_options = options;
+
+ status = execute_ss_command(DIGEST_CHECK_CMD,
+ (uint8_t* )&l_options,
+ 4u,
+ NULL_BUFFER,
+ 0u,
+ mb_offset,
+ 0u);
+ return status;
+}
+
+/***************************************************************************//**
+ * SYS_iap_service()
+ * See "core_sysservices_pf.h" for details of how to use this function.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+)
+{
+ uint8_t status = SYS_PARAM_ERR;
+ uint16_t l_mb_offset = 0u;
+ uint16_t cmd_data_size = 0u;
+ uint8_t* cmd_data = NULL_BUFFER;
+ bool invalid_param = false;
+
+ if (((IAP_PROGRAM_BY_SPIIDX_CMD == iap_cmd)
+ || (IAP_VERIFY_BY_SPIIDX_CMD == iap_cmd))
+ && (1u == spiaddr))
+ {
+ invalid_param = true;
+ HAL_ASSERT(!invalid_param);
+ }
+
+ if (!invalid_param)
+ {
+ switch(iap_cmd)
+ {
+ case IAP_PROGRAM_BY_SPIIDX_CMD:
+ case IAP_VERIFY_BY_SPIIDX_CMD:
+ /*In SPI_IDX based program and verify commands,
+ * Mailbox is not Required. Instead of mailbox offset
+ * SPI_IDX is passed as parameter.*/
+ l_mb_offset = (uint16_t)(0xFFu & spiaddr);
+ break;
+
+ case IAP_PROGRAM_BY_SPIADDR_CMD:
+ case IAP_VERIFY_BY_SPIADDR_CMD:
+ /*In SPI_ADDR based program and verify commands,
+ * Mailbox is Required*/
+ l_mb_offset = mb_offset;
+ /*command data size is four bytes holding the
+ * SPI Address in it.*/
+ cmd_data_size = 4u;
+ cmd_data = (uint8_t*)&spiaddr;
+ break;
+
+ case IAP_AUTOUPDATE_CMD:
+ /*In auto update command Mailbox is not Required*/
+ l_mb_offset = 0u;
+ break;
+
+ default:
+ l_mb_offset = 0u;
+
+ }
+
+ status = execute_ss_command(
+ (uint8_t)iap_cmd,
+ cmd_data,
+ cmd_data_size,
+ NULL_BUFFER,
+ 0,
+ (uint16_t)l_mb_offset,
+ 0);
+ }
+
+ return status;
+}
+
+/***************************************************************************//**
+ Internal functions.
+*/
+/*
+This function executes the SS command. If Mailbox input data is required by the
+it will first load it from cmd_data into the Mailbox. If the service requires
+the response data to be read from mailbox, it will do so and store it in p_response.
+*/
+static uint8_t execute_ss_command
+(
+ uint8_t cmd_opcode,
+ const uint8_t* cmd_data,
+ uint16_t cmd_data_size,
+ const uint8_t* p_response,
+ uint16_t response_size,
+ uint16_t mb_offset,
+ uint16_t response_offset
+)
+{
+ /* Pointer used during Writing to Mailbox memory. */
+ uint32_t status = 0u;
+ uint16_t idx = 0u;
+ uint16_t ss_command = 0u;
+ uint32_t* word_buf;
+ uint16_t timeout_count = SS_TIMEOUT_COUNT;
+
+ /* making sure that the system controller is not executing any service i.e.
+ SS_USER_BUSY is gone 0 */
+
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_BUSY_TIMEOUT;
+ }
+ }
+
+ /* Form the SS command: bit 0to6 is the opcode, bit 7to15 is the Mailbox offset
+ For some services this field has another meaning
+ (e.g. for IAP bitstream auth. it means spi_idx) */
+ ss_command = ((mb_offset << 7u) | (cmd_opcode & 0x7Fu));
+
+ /* Load the command register with the SS request command code*/
+ HAL_set_32bit_reg(g_css_pf_base_addr, SS_CMD, ss_command);
+
+ if (cmd_data_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == cmd_data));
+ HAL_ASSERT(!(cmd_data_size % 4u));
+
+ /* Load the MBX_WCNT register with number of words */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WCNT, (cmd_data_size/4u));
+
+ /* Load the MBX_WADDR register with offset of input data (write to Mailbox)
+ For all the services this offset remains either 0 or Not applicable
+ for the services in which no Mailbox write is required.*/
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WADDR, (0x00u + mb_offset));
+
+ }
+
+ if (response_size > 0u)
+ {
+ HAL_ASSERT(!(NULL_BUFFER == p_response));
+ HAL_ASSERT(!(response_size % 4u));
+
+ /*
+ Load the MBX_RWCNT register with number of words to be read from Mailbox
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RCNT, (response_size/4u));
+
+ /*
+ Load the MBX_RADRDESC register with offset address within the mailbox
+ format for that particular service.
+ It will be 0 for the services where there is no output data from G5CONTROL
+ is expected.
+ This function assumes that this value is pre-calculated by service specific
+ functions as this value is fixed for each service.
+ */
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_RADDR, (response_offset + mb_offset));
+ }
+
+ /*Set the request bit in SYS_SERV_REQ register to start the service*/
+ HAL_set_32bit_reg_field(g_css_pf_base_addr, SS_REQ_REQ, 0x01u);
+
+ if (cmd_data_size > 0u)
+ {
+ word_buf = (uint32_t*)cmd_data;
+
+ /* Write the user data into mail box. */
+ for (idx = 0u; idx < (cmd_data_size/4u); idx++)
+ {
+ HAL_set_32bit_reg( g_css_pf_base_addr, MBX_WDATA, word_buf[idx]);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ if (response_size > 0u)
+ {
+ word_buf = (uint32_t*)p_response;
+
+ for (idx = 0u; idx < (response_size/4u); idx++)
+ {
+ while (0u == HAL_get_32bit_reg_field(g_css_pf_base_addr,
+ SS_USER_RDVLD))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+ word_buf[idx] = HAL_get_32bit_reg(g_css_pf_base_addr, MBX_RDATA);
+ }
+ }
+
+ timeout_count = SS_TIMEOUT_COUNT;
+ /* make sure that service is complete i.e. SS_USER_BUSY is gone 0 */
+ while (1u == HAL_get_32bit_reg_field(g_css_pf_base_addr, SS_USER_BUSY))
+ {
+ --timeout_count;
+
+ if (timeout_count == 0)
+ {
+ return SS_USER_RDVLD_TIMEOUT;
+ }
+ }
+
+ /* Read the status returned by System Controller */
+ status = HAL_get_32bit_reg(g_css_pf_base_addr, SS_STAT);
+
+ return (uint8_t)status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
new file mode 100644
index 0000000..8e0ebb6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/core_sysservices_pf.h
@@ -0,0 +1,1249 @@
+/*******************************************************************************
+ * Copyright 2019-2023 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
+ * CoreSysServices_PF bare metal driver.
+ */
+/*=========================================================================*//**
+ @mainpage CoreSysServices_PF Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The PolarFire System Services (PF_SYSTEM_SERVICES) SgCore enables executing
+ the system services on the PolarFire and PolarFire SoC device. The system services
+ are the system controller actions initiated by the System Controller's System
+ Service Interface (SSI). The PolarFire System Services "SgCore" provides a
+ method to initiate these system services. The PF_SYSTEM_SERVICES interacts
+ with the system controller on SSI and Mailbox interface to initiate system
+ services, exchange data required for that services, and to know the successful
+ completion or error status.
+
+ The PF_SYSTEM_SERVICES provides an APB interface for controlling the registers
+ functions for controlling the PF_SYSTEM_SERVICES as part of a bare metal system
+ register implemented within it. This software driver provides a set of where no
+ part of an operating system but the implementation of the adaptation layer
+ operating system is available. This driver is adapted for use in
+ between this driver and the operating system's driver model is outside the
+ scope of this driver.
+
+ ## Features
+ The CoreSysServices_PF driver provides the following features:
+ - Executing device and design information services
+ - Executing design services
+ - Executing data security services
+ - Executing Fabric services
+
+ The CoreSysServices_PF driver is provided as C source code.
+
+ @section Driver Configuration
+ The application software should configure the CoreSysServices_PF driver through
+ calling the SYS_init() function. Only one instance of PF_SYSTEM_SERVICES SgCore is
+ supported. No additional configuration files are required to use the driver.
+ If using this driver on RT PolarFire device FPGA, define RT_DEVICE_FAMILY
+ macro in application.
+
+ @section theory_op Theory of Operation
+ The CoreSysServices_PF driver provides access to the PolarFire system services.
+ These system services are grouped into the following categories:
+
+ Device and Design Information Service
+ - Serial Number Service
+ - USERCODE Service
+ - Design Info Service
+ - Device Certificate Services
+ - Read Digests
+ - Query Security
+ - Read Debug Info
+ - Read eNVM param
+
+ Design Services
+ - Bitstream authentication service
+ - IAP bitstream authentication service
+
+ Data Security Services
+ - Digital Signature Service
+ - Secure NVM (SNVM) Functions
+ - PUF Emulation Service
+ - Nonce Service
+
+ Fabric Services
+ - Digest Check Service
+ - In Application programming(IAP)/Auto-Update service
+
+ Initialization and Configuration
+
+ The CoreSysServices_PF driver is initialized by calling the SYS_init()
+ function. The SYS_init() function must be called before calling any other
+ CoreSysServices_PF driver functions.
+
+ Device and Design Information Services
+
+ The CoreSysServices_PF driver is used to read information about the device
+ and the design using the following functions:
+ - SYS_get_serial_number()
+ - SYS_get_user_code()
+ - SYS_get_design_info()
+ - SYS_get_device_certificate()
+ - SYS_read_digest()
+ - SYS_query_security()
+ - SYS_read_debug_info()
+
+ Design Authentication Services
+
+ The CoreSysServices_PF driver is used to execute design services using the
+ following functions:
+ - SYS_bitstream_authenticate_service()
+ - SYS_IAP_image_authenticate_service()
+
+ Data Security Services
+
+ The CoreSysServices_PF driver is used to execute data security services
+ using the following functions:
+ - SYS_digital_signature_service()
+ - SYS_secure_nvm_write()
+ - SYS_secure_nvm_read()
+ - SYS_puf_emulation_service ()
+ - SYS_nonce_service ()
+
+ Executing Fabric Services
+
+ The CoreSysServices_PF driver is used to execute fabric services using the
+ following functions:
+ - SYS_digest_check_service()
+ - SYS_iap_service()
+
+ All the service execution functions return the 8-bit status, which is returned
+ by the system controller on executing the given service. A '0' value indicates
+ successful execution of that service. A non-zero value indicates error.
+ The error codes for each service are different. See individual function
+ description to know the exact meanings of the error codes for each service.
+
+ The function descriptions in this file mainly focus on the details required
+ by the user to use the APIs provided by this driver to execute the services.
+ To know the complete details of the system services, see the
+ PolarFire FPGA and PolarFire SoC FPGA System Services [document](https://onlinedocs.microchip.com/pr/GUID-1409CF11-8EF9-4C24-A94E-70979A688632-en-US-3/index.html)
+
+ *//*=========================================================================*/
+#ifndef __CORE_SYSSERV_PF_H
+#define __CORE_SYSSERV_PF_H 1
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#include "hal_assert.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+* # Service Execution Success and Error Status Codes
+*
+* The following status codes are the return values from the system service functions.
+* For any service, a return value '0' indicates that the service was executed
+* successfully. A non-zero return value indicates that the service was not
+* executed successfully. For all the services, the return value represents the
+* status code returned by the system controller for the respective service,
+* except the values SYS_PARAM_ERR, SS_USER_BUSY_TIMEOUT, and SS_USER_RDVLD_TIMEOUT.
+* These three values indicate the error conditions detected by this driver and
+* they do not overlap with the status code returned by the system controller for
+* any of the system service.
+*
+* SYS_SUCCESS
+* System service executed successfully
+*
+* SYS_PARAM_ERR
+* System service cannot be executed as one or more parameters are not as
+* expected by this driver. No read/write access is performed with the
+* IP.
+*
+* SS_USER_BUSY_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for the system service to complete. The System Service
+* completion is indicated by de-assertion of the SS_USER_BUSY bit by the
+* IP.
+*
+* SS_USER_RDVLD_TIMEOUT
+* The System service request is initiated and the driver timed-out while
+* waiting for SS_USER_RDVLD bit, which indicates availability of data to
+* be read from the mailbox, to become active.
+*/
+#define SYS_SUCCESS 0u
+#define SYS_PARAM_ERR 0xFFu
+#define SS_USER_BUSY_TIMEOUT 0xFAu
+#define SS_USER_RDVLD_TIMEOUT 0xFBu
+
+/**
+* # System Service Timeout Count
+*
+* The SS_TIMEOUT_COUNT value is used by the driver as a timeout count
+* while waiting for either the SS_USER_BUSY or SS_USER_RDVLD. This empirical
+* value is sufficiently large so that the operations are falsely
+* timeout in the normal circumstance. It is provided as a way to provide
+* more debug information to the application in case there are some
+* unforeseen issues. You may change this value for your need based on your
+* system design.
+*/
+#define SS_TIMEOUT_COUNT 40000u
+/*
+ * SYS_DCF_DEVICE_MISMATCH
+ * Public key or FSN do not match device
+ *
+ *
+ * SYS_DCF_INVALID_SIGNATURE
+ * Certificate signature is invalid
+ *
+ * SYS_DCF_SYSTEM_ERROR
+ * PUF or storage failure
+ */
+#define SYS_DCF_DEVICE_MISMATCH 1u
+#define SYS_DCF_INVALID_SIGNATURE 2u
+#define SYS_DCF_SYSTEM_ERROR 3u
+
+/*
+ * SYS_NONCE_PUK_FETCH_ERROR
+ * Error fetching PUK
+ *
+ * SYS_NONCE_SEED_GEN_ERROR
+ * Error generating seed
+ */
+#define SYS_NONCE_PUK_FETCH_ERROR 1u
+#define SYS_NONCE_SEED_GEN_ERROR 2u
+
+/**
+ * # Secure Nvm Write Error Codes
+ *
+ * SNVM_WRITE_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_WRITE_FAILURE
+ * PNVM program/verify failed
+ *
+ * SNVM_WRITE_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ * SNVM_WRITE_NOT_PERMITTED
+ * Write is not permitted
+ */
+#define SNVM_WRITE_INVALID_SNVMADDR 1u
+#define SNVM_WRITE_FAILURE 2u
+#define SNVM_WRITE_SYSTEM_ERROR 3u
+#define SNVM_WRITE_NOT_PERMITTED 4u
+
+/**
+ * # Secure Nvm Read Error Codes
+ *
+ * SNVM_READ_INVALID_SNVMADDR
+ * Illegal page address
+ *
+ * SNVM_READ_AUTHENTICATION_FAILURE
+ * Storage corrupt or incorrect USK
+ *
+ * SNVM_READ_SYSTEM_ERROR
+ * PUF or storage failure
+ *
+ */
+#define SNVM_READ_INVALID_SNVMADDR 1u
+#define SNVM_READ_AUTHENTICATION_FAILURE 2u
+#define SNVM_READ_SYSTEM_ERROR 3u
+
+/**
+ * # Digital Signature Service Error Codes
+ *
+ * DIGITAL_SIGNATURE_FEK_FAILURE_ERROR
+ * Error retrieving FEK
+ *
+ * DIGITAL_SIGNATURE_DRBG_ERROR
+ * Failed to generate nonce
+ *
+ * DIGITAL_SIGNATURE_ECDSA_ERROR
+ * ECDSA failed
+ */
+#define DIGITAL_SIGNATURE_FEK_FAILURE_ERROR 1u
+#define DIGITAL_SIGNATURE_DRBG_ERROR 2u
+#define DIGITAL_SIGNATURE_ECDSA_ERROR 3u
+
+/**
+ * # Digest Check Error Codes
+ *
+ * NOTE: When these error occur, the DIGEST tamper flag is triggered.
+ *
+ * DIGEST_CHECK_FABRICERR
+ * Fabric digest check error
+ *
+ * DIGEST_CHECK_CCERR
+ * UFS Fabric Configuration (CC) segment digest check error
+ *
+ * DIGEST_CHECK_SNVMERR
+ * ROM digest in SNVM segment digest check error
+ *
+ * DIGEST_CHECK_ULERR
+ * UFS UL segment digest check error
+ *
+ * DIGEST_CHECK_UK0ERR
+ * UKDIGEST0 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK1ERR
+ * UKDIGEST1 in User Key segment digest check error
+ *
+ * DIGEST_CHECK_UK2ERR
+ * UKDIGEST2 in User Key segment (UPK1) digest check error
+ *
+ * DIGEST_CHECK_UK3ERR
+ * UKDIGEST3 in User Key segment (UK1) digest check error
+ *
+ * DIGEST_CHECK_UK4ERR
+ * UKDIGEST4 in User Key segment (DPK) digest check error
+ *
+ * DIGEST_CHECK_UK5ERR
+ * UKDIGEST5 in User Key segment (UPK2) digest check error
+ *
+ * DIGEST_CHECK_UK6ERR
+ * UKDIGEST6 in User Key segment (UK2) digest check error
+ *
+ * DIGEST_CHECK_UPERR
+ * UFS Permanent Lock (UPERM) segment digest check error
+ *
+ * DIGEST_CHECK_SYSERR
+ * M3 ROM, Factory and Factory Key Segments digest check error
+ *
+ */
+#define DIGEST_CHECK_FABRICERR 0x00u
+#define DIGEST_CHECK_CCERR 0x01u
+#define DIGEST_CHECK_SNVMERR 0x02u
+#define DIGEST_CHECK_ULERR 0x03u
+#define DIGEST_CHECK_UK0ERR 0x04u
+#define DIGEST_CHECK_UK1ERR 0x05u
+#define DIGEST_CHECK_UK2ERR 0x06u
+#define DIGEST_CHECK_UK3ERR 0x07u
+#define DIGEST_CHECK_UK4ERR 0x08u
+#define DIGEST_CHECK_UK5ERR 0x09u
+#define DIGEST_CHECK_UK6ERR 0x10u
+#define DIGEST_CHECK_UPERR 0x11u
+#define DIGEST_CHECK_SYSERR 0x12u
+
+/**
+ * # Bitstream Authentication and Iap Bitstream Authentication Return Status
+ *
+ * BSTREAM_AUTH_CHAINING_MISMATCH_ERR
+ * Validator or hash chaining mismatch. Incorrectly constructed bitstream or
+ * wrong key used.
+ *
+ * BSTREAM_AUTH_UNEXPECTED_DATA_ERR
+ * Unexpected data received.
+ * Additional data received after end of EOB component.
+ *
+ * BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR
+ * Invalid/corrupt encryption key.
+ * The requested key mode is disabled or the key could not be read/reconstructed.
+ *
+ * BSTREAM_AUTH_INVALID_HEADER_ERR
+ * Invalid component header
+ *
+ * BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR
+ * Back level not satisfied
+ *
+ * BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR
+ * Illegal bitstream mode.
+ * Requested bitstream mode is disabled by user security.
+ *
+ * BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR
+ * DSN binding mismatch
+ *
+ * BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR
+ * Illegal component sequence
+ *
+ * BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR
+ * Insufficient device capabilities
+ *
+ * BSTREAM_AUTH_INCORRECT_DEVICEID_ERR
+ * Incorrect DEVICEID
+ *
+ * BSTREAM_AUTH_PROTOCOL_VERSION_ERR
+ * Unsupported bitstream protocol version (regeneration required)
+ *
+ * BSTREAM_AUTH_VERIFY_ERR
+ * Verify not permitted on this bitstream
+ *
+ * BSTREAM_AUTH_INVALID_DEV_CERT_ERR
+ * Invalid Device Certificate.
+ * Device SCAC is invalid or not present.
+ *
+ * BSTREAM_AUTH_INVALID_DIB_ERR
+ * Invalid DIB
+ *
+ * BSTREAM_AUTH_SPI_NOT_MASTER_ERR
+ * Device not in SPI Master Mode.
+ * Error may occur only when bitstream is executed through IAP mode.
+ *
+ * BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ * Occurs when no valid image pointers are found.
+ *
+ * BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR
+ * No valid images found.
+ * Error may occur when bitstream is executed through IAP mode via Index Mode.
+ * Occurs when No valid image pointers are found.
+ *
+ * BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR
+ * Programmed design version is newer than AutoUpdate image found.
+ * Error may occur when bitstream is executed through Auto Update mode.
+ *
+ * BSTREAM_AUTH_INVALID_IMAGE_ERR
+ * Selected image was invalid and no recovery was performed due to valid design
+ * in device.
+ * Error may occur only when bitstream is executed through Auto Update or IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR
+ * Selected and Recovery image failed to program.
+ * Error may occur only when bitstream is executed through Auto Update or
+ * IAP mode
+ * (This error is here for completeness but only can be observed by running the
+ * READ_DEBUG_INFO instruction and looking at IAP Error code field).
+ *
+ * BSTREAM_AUTH_ABORT_ERR
+ * Abort.
+ * Non-bitstream instruction executed during bitstream loading.
+ *
+ * BSTREAM_AUTH_NVMVERIFY_ERR
+ * Fabric/UFS verification failed (min or weak limit)
+ *
+ * BSTREAM_AUTH_PROTECTED_ERR
+ * Device security prevented modification of non-volatile memory
+ *
+ * BSTREAM_AUTH_NOTENA
+ * Programming mode not enabled
+ *
+ * BSTREAM_AUTH_PNVMVERIFY
+ * pNVM verify operation failed
+ *
+ * BSTREAM_AUTH_SYSTEM
+ * System hardware error (PUF or DRBG)
+ *
+ * BSTREAM_AUTH_BADCOMPONENT
+ * An internal error was detected in a component payload
+ *
+ * BSTREAM_AUTH_HVPROGERR
+ * HV programming subsystem failure (pump failure)
+ *
+ * BSTREAM_AUTH_HVSTATE
+ * HV programming subsystem in unexpected state (internal error)
+ *
+ */
+#define BSTREAM_AUTH_CHAINING_MISMATCH_ERR 1
+#define BSTREAM_AUTH_UNEXPECTED_DATA_ERR 2
+#define BSTREAM_AUTH_INVALID_ENCRY_KEY_ERR 3
+#define BSTREAM_AUTH_INVALID_HEADER_ERR 4
+#define BSTREAM_AUTH_BACK_LEVEL_NOT_SATISFIED_ERR 5
+#define BSTREAM_AUTH_ILLEGAL_BITSTREAM_MODE_ERR 6
+#define BSTREAM_AUTH_DNS_BINDING_MISMATCH_ERR 7
+#define BSTREAM_AUTH_ILLEGAL_COMPONENT_SEQUENCE_ERR 8
+#define BSTREAM_AUTH_INSUFF_DEVICE_CAPAB_ERR 9
+#define BSTREAM_AUTH_INCORRECT_DEVICEID_ERR 10
+#define BSTREAM_AUTH_PROTOCOL_VERSION_ERR 11
+#define BSTREAM_AUTH_VERIFY_ERR 12
+#define BSTREAM_AUTH_INVALID_DEV_CERT_ERR 13
+#define BSTREAM_AUTH_INVALID_DIB_ERR 14
+#define BSTREAM_AUTH_SPI_NOT_MASTER_ERR 21
+#define BSTREAM_AUTH_AUTOIAP_NO_VALID_IMAGE_ERR 22
+#define BSTREAM_AUTH_INDEXIAP_NO_VALID_IMAGE_ERR 23
+#define BSTREAM_AUTH_NEWER_DESIGN_VERSION_ERR 24
+/* 25 Reserved */
+#define BSTREAM_AUTH_INVALID_IMAGE_ERR 26
+#define BSTREAM_AUTH_IMAGE_PROGRAM_FAILED_ERR 27
+#define BSTREAM_AUTH_ABORT_ERR 127
+#define BSTREAM_AUTH_NVMVERIFY_ERR 128
+#define BSTREAM_AUTH_PROTECTED_ERR 129
+#define BSTREAM_AUTH_NOTENA 130
+#define BSTREAM_AUTH_PNVMVERIFY 131
+#define BSTREAM_AUTH_SYSTEM 132
+#define BSTREAM_AUTH_BADCOMPONENT 133
+#define BSTREAM_AUTH_HVPROGERR 134
+#define BSTREAM_AUTH_HVSTATE 135
+
+/***************************************************************************//**
+ * # Mailbox ECC Status
+ * Provides ECC status when the mailbox is read. The values are as follows:
+ * 00: No ECC errors detected, data is correct.
+ * 01: Exactly one bit error occurred and has been corrected.
+ * 10: Exactly two bits error occurred and no correction performed.
+ * 11: Reserved.
+ */
+#define SYS_MBOX_ECC_NO_ERROR_MASK 0x00u
+#define SYS_MBOX_ONEBIT_ERROR_CORRECTED_MASK 0x40u
+#define SYS_MBOX_TWOBIT_ERROR_MASK 0xC0u
+
+/***************************************************************************//**
+ * Service request command opcodes:
+*/
+#define SERIAL_NUMBER_REQUEST_CMD 0x00u
+#define USERCODE_REQUEST_CMD 0x01u
+#define DESIGN_INFO_REQUEST_CMD 0x02u
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0x03u
+#define READ_DIGEST_REQUEST_CMD 0x04u
+#define QUERY_SECURITY_REQUEST_CMD 0x05u
+#define READ_DEBUG_INFO_REQUEST_CMD 0x06u
+#define READ_ENVM_PARAM_REQUEST_CMD 0x07u
+#define SNVM_NON_AUTHEN_TEXT_REQUEST_CMD 0x10u
+#define SNVM_AUTHEN_TEXT_REQUEST_CMD 0x11u
+#define SNVM_AUTHEN_CIPHERTEXT_REQUEST_CMD 0x12u
+#define SNVM_READ_REQUEST_CMD 0x18u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_REQUEST_CMD 0x19u
+#define PUF_EMULATION_SERVICE_REQUEST_CMD 0x20u
+#define NONCE_SERVICE_REQUEST_CMD 0x21u
+#define DIGITAL_SIGNATURE_DER_FORMAT_REQUEST_CMD 0x1Au
+
+#define BITSTREAM_AUTHENTICATE_CMD 0x23u
+#define IAP_BITSTREAM_AUTHENTICATE_CMD 0x22u
+
+#define DIGEST_CHECK_CMD 0x47u
+
+#define IAP_PROGRAM_BY_SPIIDX_CMD 0x42u
+#define IAP_VERIFY_BY_SPIIDX_CMD 0x44u
+#define IAP_PROGRAM_BY_SPIADDR_CMD 0x43u
+#define IAP_VERIFY_BY_SPIADDR_CMD 0x45u
+#define IAP_AUTOUPDATE_CMD 0x46u
+
+/***************************************************************************//**
+ * Service request Mailbox return data length
+ */
+#define SERIAL_NUMBER_RESP_LEN 16u
+#define USERCODE_RESP_LEN 4u
+#define DESIGN_INFO_RESP_LEN 36u
+#define DEVICE_CERTIFICATE_RESP_LEN 1024u
+#define READ_DIGEST_RESP_LEN 416u
+#define QUERY_SECURITY_RESP_LEN 9u
+#define READ_DEBUG_INFO_RESP_LEN 76u
+#define READ_ENVM_PARAM_RESP_LEN 256u
+#define NONCE_SERVICE_RESP_LEN 32u
+
+#define PUF_EMULATION_SERVICE_CMD_LEN 20u
+#define PUF_EMULATION_SERVICE_RESP_LEN 32u
+
+#define DIGITAL_SIGNATURE_HASH_LEN 48u
+#define DIGITAL_SIGNATURE_RAW_FORMAT_RESP_SIZE 96u
+#define DIGITAL_SIGNATURE_DER_FORMAT_RESP_SIZE 104u
+
+#define USER_SECRET_KEY_LEN 12u
+
+/* Same driver can be used on PolarFire SoC platform and the response length
+ * is different for PolarFire SoC. Constants defined below are used only when the
+ * PF System services driver is used with PolarFire SoC Platform.
+ */
+#define READ_DIGEST_MPFS_RESP_LEN 576u
+#define QUERY_SECURITY_MPFS_RESP_LEN 33u
+
+/* SNVM Input data length from sNVM write. */
+#ifndef RT_DEVICE_FAMILY
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 256u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 252u
+#else
+/* SNVMADDR + RESERVED + PT + USK */
+#define NON_AUTHENTICATED_TEXT_DATA_LEN 224u
+
+/* SNVMADDR + RESERVED + PT */
+#define AUTHENTICATED_TEXT_DATA_LEN 220u
+#endif
+
+/**
+ * # Digest Check Input Options
+ *
+ * DIGEST_CHECK_FABRIC
+ * Carry out digest check on Fabric
+ *
+ * DIGEST_CHECK_CC
+ * Carry out digest check on UFS Fabric Configuration (CC) segment
+ *
+ * DIGEST_CHECK_SNVM
+ * Carry out digest check on ROM digest in SNVM segment
+ *
+ * DIGEST_CHECK_UL
+ * Carry out digest check on UFS UL segment
+ *
+ * DIGEST_CHECK_UKDIGEST0
+ * Carry out digest check on UKDIGEST0 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST1
+ * Carry out digest check on UKDIGEST1 in User Key segment
+ *
+ * DIGEST_CHECK_UKDIGEST2
+ * Carry out digest check on UKDIGEST2 in User Key segment (UPK1)
+ *
+ * DIGEST_CHECK_UKDIGEST3
+ * Carry out digest check on UKDIGEST3 in User Key segment (UK1)
+ *
+ * DIGEST_CHECK_UKDIGEST4
+ * Carry out digest check on UKDIGEST4 in User Key segment (DPK)
+ *
+ * DIGEST_CHECK_UKDIGEST5
+ * Carry out digest check on UKDIGEST5 in User Key segment (UPK2)
+ *
+ * DIGEST_CHECK_UKDIGEST6
+ * Carry out digest check on UKDIGEST6 in User Key segment (UK2)
+ *
+ * DIGEST_CHECK_UPERM
+ * Carry out digest check on UFS Permanent lock (UPERM) segment
+ *
+ * DIGEST_CHECK_SYS
+ * Carry out digest check on Factory and Factory Key Segments
+ *
+ */
+#define DIGEST_CHECK_FABRIC (0x01<<0x00u) /*Fabric digest*/
+#define DIGEST_CHECK_CC (0x01<<0x01u) /*UFS Fabric Configuration (CC) segment*/
+#define DIGEST_CHECK_SNVM (0x01<<0x02u) /*ROM digest in SNVM segment*/
+#define DIGEST_CHECK_UL (0x01<<0x03u) /*UFS UL segment*/
+#define DIGEST_CHECK_UKDIGEST0 (0x01<<0x04u) /*UKDIGEST0 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST1 (0x01<<0x05u) /*UKDIGEST1 in User Key segment*/
+#define DIGEST_CHECK_UKDIGEST2 (0x01<<0x06u) /*UKDIGEST2 in User Key segment (UPK1)*/
+#define DIGEST_CHECK_UKDIGEST3 (0x01<<0x07u) /*UKDIGEST3 in User Key segment (UK1)*/
+#define DIGEST_CHECK_UKDIGEST4 (0x01<<0x08u) /*UKDIGEST4 in User Key segment (DPK)*/
+#define DIGEST_CHECK_UKDIGEST5 (0x01<<0x09u) /*UKDIGEST5 in User Key segment (UPK2)*/
+#define DIGEST_CHECK_UKDIGEST6 (0x01<<0x0au) /*UKDIGEST6 in User Key segment (UK2)*/
+#define DIGEST_CHECK_UPERM (0x01<<0x0bu) /*UFS Permanent lock (UPERM) segment*/
+#define DIGEST_CHECK_SYS (0x01<<0x0cu) /*Factory and Factory Key Segments.*/
+
+/***************************************************************************//**
+ * The function SYS_init() is used to initialize the internal data structures of
+ * this driver. Currently this function is empty.
+ *
+ * @param base_addr The base_addr parameter specifies the base address of the
+ * PF_System_services core.
+ *
+ * @return This function does not return a value.
+ */
+void
+SYS_init
+(
+ uint32_t base_addr
+);
+
+/***************************************************************************//**
+ * The function SYS_get_serial_number() is used to execute "serial number" system
+ * service.
+ *
+ * @param p_serial_number The p_serial_number parameter is a pointer to a buffer
+ * in which the data returned by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_serial_number
+(
+ const uint8_t * p_serial_number,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_user_code() is used to execute "USERCODE" system
+ * service.
+ * @param p_user_code The p_user_code parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_user_code
+(
+ const uint8_t * p_user_code,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_design_info() is used to execute "Get Design Info" system
+ * service.
+ *
+ * @param p_design_info The p_design_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied. Total size of debug information is 36 bytes.
+ * The data from the system controller includes the 256-bit
+ * user-defined design ID, 16-bit design version, and 16-bit
+ * design back level.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t
+SYS_get_design_info
+(
+ const uint8_t * p_design_info,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_get_device_certificate() is used to execute "Get Device
+ * Certificate" system service.
+ *
+ * @param p_device_certificate The p_device_certificate parameter is a pointer
+ * to a buffer in which the data returned by the
+ * system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ *
+ */
+uint8_t
+SYS_get_device_certificate
+(
+ const uint8_t * p_device_certificate,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_digest() is used to execute "Read Digest" system service.
+ *
+ * @param p_digest The p_digest parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_digest
+(
+ const uint8_t * p_digest,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_query_security() is used to execute "Query Security" system
+ * service.
+ *
+ * @param p_security_locks The p_security_locks parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means that
+ * the service was executed successfully.
+ */
+uint8_t SYS_query_security
+(
+ uint8_t * p_security_locks,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_read_debug_info() is used to execute "Read Debug info" system
+ * service.
+ *
+ * @param p_debug_info The p_debug_info parameter is a pointer to a buffer
+ * in which the data returned by system controller is
+ * copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code
+ * means that the service was executed successfully.
+ */
+uint8_t SYS_read_debug_info
+(
+ const uint8_t * p_debug_info,
+ uint16_t mb_offset
+);
+
+#ifdef CORESYSSERVICES_PFSOC
+/***************************************************************************//**
+ * The function SYS_read_envm_parameter() is used to retrieve all parameters needed
+ * for the eNVM operation and programming.
+ *
+ * NOTE: This service is available only on PolarFire SoC Platform.
+ * This service is not yet supported by PF_SYSTEM_SERVICES 3.0.100.
+ *
+ * @param p_envm_param The p_envm_param parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ * This buffer stores all the eNVM parameters.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_read_envm_parameter service will return zero if the
+ * service executed successfully, otherwise, it will return
+ * one indicating error.
+ */
+uint8_t SYS_read_envm_parameter
+(
+ uint8_t * p_envm_param,
+ uint16_t mb_offset
+);
+#endif
+/***************************************************************************//**
+ * The function SYS_puf_emulation_service() is used to authenticate a device.
+ *
+ * The SYS_puf_emulation_service() function accept a challenge comprising a
+ * 8-bit optype and 128-bit challenge and return a 256-bit response unique to
+ * the given challenge and the device.
+ *
+ * @param p_challenge The p_challenge parameter specifies the 128-bit challenge
+ * to generate the 256-bits unique response.
+ *
+ * @param op_type The op_type parameter specifies the operational parameter
+ * to generate the 256-bits unique response.
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer where
+ * the data returned which is the response by system controller
+ * is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_puf_emulation_service function will return zero
+ * if the service executed successfully, otherwise, it will
+ * return one indicating error.
+ */
+uint8_t SYS_puf_emulation_service
+(
+ const uint8_t * p_challenge,
+ uint8_t op_type,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_digital_signature_service() function is used to generate P-384 ECDSA
+ * signature based on SHA384 hash value.
+ *
+ * @param p_hash The p_hash parameter is a pointer to the buffer which
+ * contain the 48 bytes SHA384 Hash value (input value).
+ *
+ * @param format The format parameter specifies the output format of
+ * generated SIGNATURE field. The different types of output
+ * signature formats are as follow:
+ * - DIGITAL_SIGNATURE_RAW_FORMAT
+ * - DIGITAL_SIGNATURE_DER_FORMAT
+ *
+ * @param p_response The p_response parameter is a pointer to a buffer that
+ * contains the generated ECDSA signature. The field may be
+ * 96 bytes or 104 bytes depending upon the output format.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_digital_signature_service
+(
+ const uint8_t* p_hash,
+ uint8_t format,
+ uint8_t* p_response,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_write() function writes data in the sNVM region.
+ * Data gets stored in the following format:
+ * - Non-authenticated plaintext
+ * - Authenticated plaintext
+ * - Authenticated ciphertext
+ *
+ * Note: If you are executing this function with Authenticated plaintext
+ * or Authenticated ciphertext on a device whose sNVM was never previously
+ * written to, then the service may fail. For it to work, you must first write
+ * Authenticated data to the sNVM using Libero along with USK client and
+ * custom security. This flow generates the SMK. See UG0753 PolarFire FPGA
+ * Security User Guide for further details.
+
+ * @param format The format parameter specifies the format used to write
+ * data in sNVM region. The different type of text formats
+ * are as follow:
+ * - NON_AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_PLAINTEXT_FORMAT
+ * - AUTHENTICATED_CIPHERTEXT_FORMAT
+ *
+ * @param snvm_module The snvm_module parameter specifies the the sNVM module
+ * in which the data need to be written.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data to be stored in sNVM region. The data
+ * length to be written is fixed depending on the format
+ * parameter. If NON_AUTHENTICATED_PLAINTEXT_FORMAT is
+ * selected, then you can write 252 bytes in the sNVM module.
+ * For other two formats the data length is 236 bytes.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). This user
+ * secret key will enhance the security when authentication
+ * is used. That is, when Authenticated plaintext and
+ * Authenticated ciphertext format is selected.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_write
+(
+ uint8_t format,
+ uint8_t snvm_module,
+ const uint8_t* p_data,
+ const uint8_t* p_user_key,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_secure_nvm_read() function is used to read data present in sNVM region.
+ * User should provide USK key, if the data was programmed using authentication.
+ * If the data was written in the sNVM using the authenticated plaintext or the
+ * authenticated ciphertext service option then this service will return the
+ * valid data only when authentication is successful. For more details, see
+ * SYS_secure_nvm_write() function. If the data was written in
+ * the sNVM using the authenticated plaintext or the authenticated ciphertext
+ * service option then this service will return the valid data only when
+ * authentication is successful. For more details, see SYS_secure_nvm_write()
+ * function and its parameter description.
+ *
+ * @param snvm_module The snvm_module parameter specifies the sNVM module
+ * from which the data need to be read.
+ *
+ * @param p_user_key The p_user_key parameter is a pointer to a buffer which
+ * contain the 96-bit key USK (user secret key). User should
+ * provide same secret key which is previously used for
+ * authentication while writing data in sNVM region.
+ *
+ * @param p_admin The p_admin parameter is a pointer to the buffer where
+ * the output page admin data is stored. The page admin
+ * data is 4 bytes long.
+ *
+ * @param p_data The p_data parameter is a pointer to a buffer which
+ * contains the data read from sNVM region. User should
+ * provide the buffer large enough to store the read data.
+ *
+ * @param data_len The data_len parameter specifies the number of bytes to be
+ * read from sNVM.
+ * The application should know whether the data written in the
+ * chose sNVM module was previously stored using Authentication
+ * or not.
+ * The data_len should be 236 bytes, for authenticated data.
+ * For not authenticated data the data_len should be 252 bytes.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digital_signature_service function returns
+ * zero if the service executed successfully, otherwise, it
+ * returns non-zero values indicating error.
+ */
+uint8_t SYS_secure_nvm_read
+(
+ uint8_t snvm_module,
+ const uint8_t* p_user_key,
+ uint8_t* p_admin,
+ uint8_t* p_data,
+ uint16_t data_len,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The function SYS_nonce_service() is used to issue "Nonce Service" system
+ * service to the system controller.
+ *
+ * @param p_nonce The p_nonce parameter is a pointer to a buffer
+ * in which the data returned by system controller is copied.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return This function returns the status code returned by the
+ * system controller for this service. A '0' status code means
+ * that the service was executed successfully and a non-zero
+ * value indicates error. See the document link
+ * provided in the theory of operation section to know more
+ * about the service and service response.
+ */
+uint8_t SYS_nonce_service
+(
+ const uint8_t * p_nonce,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_bitstream_authenticate_service() function is used to authenticate
+ * the Bitstream which is located in SPI through a system service routine. Prior
+ * to using the IAP service, it may be required to first validate the new
+ * bitstream before committing the device to reprogramming, thus avoiding the
+ * need to invoke recovery procedures if the bitstream is invalid.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_flash_address
+ * The spi_flash_address parameter specifies the address within
+ * SPI Flash memory where the bit-stream is stored.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_bitstream_authenticate_service function will return
+ * zero if the service executed successfully and the non-zero
+ * response from system controller indicates error. See
+ * the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_bitstream_authenticate_service
+(
+ uint32_t spi_flash_address,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_IAP_image_authenticate_service() function is used to authenticate
+ * the IAP image which is located in SPI through a system service routine. The
+ * service checks the image descriptor and the referenced bitstream and optional
+ * initialization data. If the image is authenticated successfully, then the
+ * image is guaranteed to be valid when used by an IAP function.
+ *
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ *
+ * @param spi_idx
+ * The spi_idx parameter specifies the index in the SPI directory to
+ * be used where the IAP bit-stream is stored.
+ * Note: To support recovery SPI_IDX=1 should be an empty slot and the recovery
+ * image should be located in SPI_IDX=0. Since SPI_IDX=1 should be an
+ * empty slot, it shouldn’t be passed into the system service.
+ *
+ * @return The SYS_IAP_image_authenticate_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Please
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_IAP_image_authenticate_service
+(
+ uint8_t spi_idx
+);
+
+/***************************************************************************//**
+ * The SYS_digest_check_service() function is used to Recalculates and compares
+ * digests of selected non-volatile memories. If the fabric digest is to be
+ * checked, then the user design must follow all prerequisite steps for the
+ * FlashFreeze service before invoking this service.
+ * This service is applicable to bitstreams stored in SPI Flash memory only.
+ * @param options
+ * The options parameter specifies the digest check options which
+ * indicate the area on which the digest check should be performed.
+ * Below is the list of options. You can OR these options to indicate
+ * to perform digest check on multiple segments.
+ * Note: The options parameter is of 2 bytes when used with PF
+ * device and 4 bytes when used with PolarFire SoC device.
+ * Options[i] | Description
+ * ---------------|----------------------------------
+ * 0x01 | Fabric digest
+ * 0x02 | Fabric Configuration (CC) segment
+ * 0x04 | ROM digest in SNVM segment
+ * 0x08 | UL segment
+ * 0x10 | UKDIGEST0 in User Key segment
+ * 0x20 | UKDIGEST1 in User Key segment
+ * 0x40 | UKDIGEST2 in User Key segment (UPK1)
+ * 0x80 | UKDIGEST3 in User Key segment (UK1)
+ * 0x100 | UKDIGEST4 in User Key segment (DPK)
+ * 0x200 | UKDIGEST5 in User Key segment (UPK2)
+ * 0x400 | UKDIGEST6 in User Key segment (UK2)
+ * 0x800 | UFS Permanent lock (UPERM) segment
+ * 0x1000 | Factory and Factory Key Segments.
+ * 0x2000 | UKDIGEST7 in User Key segment (HWM) (PFSoC)
+ * 0x4000 | ENVMDIGEST (PFSoC only)
+ * 0x8000 | UKDIGEST8 for MSS Boot Info (PFSoC only)
+ * 0x10000 | SNVM_RW_ACCESS_MAP Digest (PFSoC only)
+ * 0x20000 | SBIC revocation digest (PFSoC only)
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ *
+ * @return The SYS_digest_check_service function will return
+ * zero if the service executed successfully the non-zero
+ * response from system controller indicates error. Pleaes
+ * refer to the document link provided in the theory of
+ * operation section to know more about the service and service
+ * response.
+ */
+uint8_t SYS_digest_check_service
+(
+ uint32_t options,
+ uint16_t mb_offset
+);
+
+/***************************************************************************//**
+ * The SYS_iap_service() function is used to IAP service. The IAP service allows
+ * the user to reprogram the device without the need for an external master. The
+ * user design writes the bitstream to be programmed into a SPI Flash connected
+ * to the SPI port. When the service is invoked, the System Controller
+ * automatically reads the bitstream from the SPI flash and programs the device.
+ * The service allows the image to be executed in either VERIFY or PROGRAM modes.
+ * Another option for IAP is to perform the auto-update sequence. In this case
+ * the newest image of the first two images in the SPI directory is chosen to be
+ * programmed.
+ *
+ * @param iap_cmd
+ * The iap_cmd parameter specifies the specific IAP command which
+ * depends upon VERIFY or PROGRAM modes and the SPI address method.
+ * iap_cmd | Description
+ * -----------------------|------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | IAP program.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Fabric Configuration (CC) segment
+ * IAP_PROGRAM_BY_SPIADDR_CMD | ROM digest in SNVM segment
+ * IAP_VERIFY_BY_SPIADDR_CMD | UL segment
+ * IAP_AUTOUPDATE_CMD | UKDIGEST0 in User Key segment
+ *
+ * @param spiaddr
+ * The spiaddr parameter specifies either the index
+ * in the SPI directory or the SPI address in the SPI Flash memory.
+ * Below is the list of the possible meaning of spiaddr parameter
+ * in accordance with the iap_cmd parameter.
+ * iap_cmd | spiaddr
+ * ----------------------|-----------------
+ * IAP_PROGRAM_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_VERIFY_BY_SPIIDX_CMD | Index in the SPI directory.
+ * IAP_PROGRAM_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_VERIFY_BY_SPIADDR_CMD | SPI address in the SPI Flash memory
+ * IAP_AUTOUPDATE_CMD | spiaddr is ignored as No index/address required for this command.
+ *
+ * @param mb_offset The mb_offset parameter specifies the offset from
+ * the start of Mailbox where the data related to this service
+ * is available. Note that all accesses to the mailbox
+ * are of word length (4 bytes). Value '10' of this parameter
+ * means that the data access area for this service
+ * starts from 11th word (offset 10) in the Mailbox.
+ * Note: For the IAP services with command IAP_PROGRAM_BY_SPIIDX_CMD and
+ * IAP_VERIFY_BY_SPIIDX_CMD To support recovery SPI_IDX=1 should be an
+ * empty slot and the recovery image should be located in SPI_IDX=0.
+ * Since SPI_IDX=1 should be an empty slot it shouldn’t be passed into
+ * the system service.
+ *
+ * @return The SYS_iap_service function will return zero if the service
+ * executed successfully and the non-zero response from system
+ * controller indicates error. Please refer to the document
+ * link provided in the theory of operation section to know
+ * more about the service and service response.
+ */
+uint8_t SYS_iap_service
+(
+ uint8_t iap_cmd,
+ uint32_t spiaddr,
+ uint16_t mb_offset
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_H */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
new file mode 100644
index 0000000..8b14b7e
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreSysServices_PF/coresysservicespf_regs.h
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * Copyright 2019-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register bit offsets and masks definitions for CoreSysServices_PF driver.
+ */
+
+#ifndef __CORE_SYSSERV_PF_REGISTERS
+#define __CORE_SYSSERV_PF_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_CMD (offset 0x04) register details
+ */
+#define SS_CMD_REG_OFFSET 0x04u
+
+#define SS_CMD_OFFSET 0x04
+#define SS_CMD_MASK 0x0000FFFFu
+#define SS_CMD_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_STAT (offset 0x08) register details
+ */
+#define SS_STAT_REG_OFFSET 0x08u
+
+#define SS_STAT_OFFSET 0x08
+#define SS_STAT_MASK 0x0000FFFFu
+#define SS_STAT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SYS_SERV_REQ (offset 0x0C) register details
+ */
+#define SS_REQ_REG_OFFSET 0x0Cu
+
+
+#define SS_REQ_REQ_OFFSET 0x0Cu
+#define SS_REQ_REQ_MASK 0x00000001UL
+#define SS_REQ_REQ_SHIFT 0u
+
+#define SS_REQ_ABUSY_OFFSET 0x0Cu
+#define SS_REQ_ABUSY_MASK 0x00000002UL
+#define SS_REQ_ABUSY_SHIFT 1u
+
+#define SS_REQ_NABUSY_OFFSET 0x0Cu
+#define SS_REQ_NABUSY_MASK 0x00000004UL
+#define SS_REQ_NABUSY_SHIFT 2u
+
+#define SS_REQ_SSBUSY_OFFSET 0x0Cu
+#define SS_REQ_SSBUSY_MASK 0x00000008UL
+#define SS_REQ_SSBUSY_SHIFT 3u
+
+#define SS_REQ_AREQ_OFFSET 0x0Cu
+#define SS_REQ_AREQ_MASK 0x00000010UL
+#define SS_REQ_AREQ_SHIFT 4u
+
+#define SS_REQ_NAREQ_OFFSET 0x0Cu
+#define SS_REQ_NAREQ_MASK 0x00000020UL
+#define SS_REQ_NAREQ_SHIFT 5u
+/*------------------------------------------------------------------------------
+ * MBX_ECCSTATUS (offset 0x10) register details
+ */
+#define MBX_ECCSTATUS_REG_OFFSET 0x10u
+
+#define MBX_ECCSTATUS_OFFSET 0x10
+#define MBX_ECCSTATUS_MASK 0x03u
+#define MBX_ECCSTATUS_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_WCNT (offset 0x14) register details
+ */
+#define MBX_WCNT_REG_OFFSET 0x14u
+
+#define MBX_WCNT_OFFSET 0x14
+#define MBX_WCNT_MASK 0x000001FFu
+#define MBX_WCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RWCNT (offset 0x18) register details
+ */
+#define MBX_RCNT_REG_OFFSET 0x18u
+
+#define MBX_RCNT_OFFSET 0x18
+#define MBX_RCNT_MASK 0x000001FFu
+#define MBX_RCNT_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WADRDESC (offset 0x1C) register details
+ */
+#define MBX_WADDR_REG_OFFSET 0x1Cu
+
+#define MBX_WADDR_OFFSET 0x1C
+#define MBX_WADDR_MASK 0x000001FFu
+#define MBX_WADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_RADRDESC (offset 0x20) register details
+ */
+#define MBX_RADDR_REG_OFFSET 0x20u
+
+#define MBX_RADDR_OFFSET 0x20
+#define MBX_RADDR_MASK 0x000001FFu
+#define MBX_RADDR_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * MBX_WDATA (offset 0x28) register details
+ */
+#define MBX_WDATA_REG_OFFSET 0x28u
+
+#define MBX_WDATA_OFFSET 0x28
+#define MBX_WDATA_MASK 0xFFFFFFFFu
+#define MBX_WDATA_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * MBX_RDATA (offset 0x2C) register details
+ */
+#define MBX_RDATA_REG_OFFSET 0x2Cu
+
+#define MBX_RDATA_OFFSET 0x2C
+#define MBX_RDATA_MASK 0xFFFFFFFFu
+#define MBX_RDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * SS_USER (offset 0x30) register details
+ */
+#define SS_USER_REG_OFFSET 0x30u
+
+#define SS_USER_BUSY_OFFSET 0x30
+#define SS_USER_BUSY_MASK 0x00000001u
+#define SS_USER_BUSY_SHIFT 0u
+
+#define SS_USER_RDVLD_OFFSET 0x30
+#define SS_USER_RDVLD_MASK 0x00000002u
+#define SS_USER_RDVLD_SHIFT 1u
+
+#define SS_USER_CMDERR_OFFSET 0x30
+#define SS_USER_CMDERR_MASK 0x00000004u
+#define SS_USER_CMDERR_SHIFT 2u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_SYSSERV_PF_REGISTERS */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 0000000..0c0a866
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,297 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 0000000..c016403
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 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 minimal FPGA tile usage within a Microchip FPGA.
+ The CoreUARTapb bare metal software driver is designed to be used in systems
+ with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provide functions that allow the use of the
+ CoreUARTapb in interrupt-driven mode but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling are not
+ 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 by calling
+ 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 is generated with fixed baud rate, 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
+ have no effect if fixed values were selected for the baud rate, character
+ size, and parity in the hardware configuration of CoreUARTapb. When fixed
+ values are selected for these hardware configuration parameters, the driver is
+ unable to 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 while calling the UART_init() function. A pointer
+ to the structure is passed to the 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.
+
+ Once initialized, the driver transmits and receives data. Transmit is
+ performed using the UART_send() function. If this function blocks, then it
+ returns only when the data passed to it has been sent to the CoreUARTapb
+ hardware. Data received by the CoreUARTapb hardware is read by the user
+ application using the UART_get_rx() function.
+
+ The UART_fill_tx_fifo() function is also provided as a part of the
+ 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 UART_polled_tx_string() function is provided to transmit a NULL-terminated
+ string in polled mode. If this function blocks, then it returns only when the
+ data passed to it has been sent to the CoreUARTapb hardware.
+
+ The UART_get_rx_status() function returns the error status of the CoreUARTapb
+ receiver. This is 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
+ ========================
+ These constants define the data length in a UART packet.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | DATA_7_BITS | Data length is 7-bits |
+ | DATA_8_BITS | Data length is 8-bits |
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ Parity Defines
+ ==============
+ These constants define parity check options.
+ | Constant | Description |
+ |-------------|---------------------------------------|
+ | NO_PARITY | No Parity bit |
+ | EVEN_PARITY | Even Parity bit |
+ | ODD_PARITY | ODD Parity bit |
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ Error Status Definitions
+ ========================
+ These constants define the different types of possible errors in UART
+ transmission of data.
+ | Constant | Description |
+ |-------------------------|---------------------------------------|
+ | UART_APB_PARITY_ERROR | Data parity error |
+ | UART_APB_OVERFLOW_ERROR | Data overflow error |
+ | UART_APB_FRAMING_ERROR | Data framing error |
+ | UART_APB_NO_ERROR | No error |
+ | UART_APB_INVALID_PARAM | Invalid parameter |
+ */
+#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
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of
+ * CoreUARTapb in your system. This structure instance identifies various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART performs 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 UART_init() function initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value that generates
+ * the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * UART_instance_t structure, which holds all data regarding
+ * this instance of the CoreUARTapb. This pointer is 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 selects 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, specifies the
+ * bit length and parity settings. This is the 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 UART_send() function is used to transmit data. It transfers the content
+ * 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 should not 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 transmission over the serial connection is 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 the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ *
+ * @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 UART_fill_tx_fifo() function 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to the
+ * 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 that
+ * contains the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes of the
+ * transmitted data.
+ * @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 UART_get_rx() function 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,
+ * depending on 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 the
+ * 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 is 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 UART_polled_tx_string() function 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 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 should not 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 is still be taking place at
+ * the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is the 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 return value is 0, if there
+ * are 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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 0000000..c123cc3
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
new file mode 100644
index 0000000..a2f4911
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.c
@@ -0,0 +1,765 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V I2C Soft IP bare-metal driver. This module is delivered as part of
+ * Extended Sub System(ESS) MIV_ESS.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_i2c.h"
+
+#define MIV_I2C_ERROR 0xFFu
+
+/*------------------------------------------------------------------------------
+ * MIV I2C transaction direction.
+ */
+#define MIV_I2C_WRITE_DIR 0u
+#define MIV_I2C_READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define MIV_I2C_NO_TRANSACTION 0u
+#define MIV_I2C_MASTER_WRITE_TRANSACTION 1u
+#define MIV_I2C_MASTER_READ_TRANSACTION 2u
+#define MIV_I2C_MASTER_SEQUENTIAL_READ_TRANSACTION 3u
+
+/*------------------------------------------------------------------------------
+ * MIV I2C HW states
+ */
+#define MIV_I2C_IDLE 0x00u
+#define MIV_I2C_TX_STA_CB 0x01u
+#define MIV_I2C_TX_DATA 0x02u
+#define MIV_I2C_RX_DATA 0x03u
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_disable_irq() disables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_disable_irq
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_enable_irq() enables the Mi-V I2C interrupt.
+ */
+void
+MIV_I2C_enable_irq
+(
+ void
+);
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_miv_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, MIV_I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(miv_i2c_instance_t));
+
+ this_i2c->base_addr = base_addr;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+)
+{
+ /* Assign the base address
+ * Clock Prescale value set
+ * MIV_I2C interrupt enabled
+ * I2C core enable
+ */
+ psr_t processor_state;
+
+ /* Disabling the interrupts */
+ processor_state = HAL_disable_interrupts();
+
+ /* Before writing to prescale reg, the core enable must be zero */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x00u);
+
+ /* Set the prescale value */
+ HAL_set_16bit_reg(this_i2c->base_addr, PRESCALE, clk_prescale);
+
+ /* Enable the MIV I2C interrupts */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_IRQ_EN, 0x01u);
+
+ /* Enable the MIV I2C core */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CTRL_CORE_EN, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* Generate I2C stop condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ HAL_restore_interrupts(processor_state);
+
+ return 0u;
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* I2C write flow
+ *
+ * Check I2C status for ongoing transaction
+ * Populate the structure with input data
+ * Generate start condition
+ * Set the write_direction and target address.
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MIV_I2C_MASTER_WRITE_TRANSACTION ;
+
+ /* Populate the i2c instance structure */
+
+ /* Set the target addr */
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* Set up the tx buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set the I2C status in progress and setup the options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+
+ /* Generate I2C start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* write target address and write bit */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_WRITE_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set WR bit to transmit start condition and control byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set current master hw state -> transmitted start condition and
+ * control byte
+ */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ psr_t processor_state;
+ uint8_t status = MIV_I2C_SUCCESS;
+
+ processor_state = HAL_disable_interrupts();
+
+ /* MIV I2C Read operation flow
+ *
+ * Check for ongoing transaction
+ * Populate the i2c instance structure
+ * Generate the start condition
+ * Set the READ_direction bit and target addr
+ */
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the MIV I2C instance structure */
+
+ this_i2c->target_addr = i2c_target_addr;
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ /* Populate read buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the BUS and ACK polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start condition */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, i2c_target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /* Toggle the IACK bit if required */
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00);
+ }
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+)
+{
+ uint8_t status = MIV_I2C_SUCCESS;
+ psr_t processor_state;
+
+ processor_state = HAL_disable_interrupts();
+
+ uint8_t read_stat = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_TIP);
+
+ /* I2C write read operation flow
+ *
+ * Used to read the data from set address offset
+ *
+ * Configure the i2c instance structure
+ * generate the start and configure the dir and target addr
+ * set wr bit to transmit the start and command byte
+ *
+ */
+
+ /* Update the transaction only when there is no ongoing I2C transaction */
+ if (this_i2c->transaction == MIV_I2C_NO_TRANSACTION)
+ {
+ this_i2c->transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+ }
+
+ this_i2c->pending_transaction = MIV_I2C_MASTER_READ_TRANSACTION;
+
+ /* Populate the I2C instance */
+
+ this_i2c->target_addr = target_addr;
+
+ /* setup the i2c direction */
+ this_i2c->dir = MIV_I2C_WRITE_DIR;
+
+ /* set up transmit buffer */
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* set up receive buffer */
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the bus and ack polling options */
+ this_i2c->bus_options = bus_options;
+ this_i2c->ack_polling_options = ack_polling_options;
+
+ /* Generate the start command */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ /* Set the WR bit to transmit the start command and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ /* Set the i2c master state and status transmitting STA and Command Byte */
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ this_i2c->master_status = MIV_I2C_IN_PROGRESS;
+
+ /*
+ * Clear interrupt if required
+ */
+ if ( MIV_I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ /* Must toggle IACK bit to clear the MIV_I2C IRQ*/
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+ }
+
+ /* Enable the I2C interrupt */
+ MIV_I2C_enable_irq();
+
+ HAL_restore_interrupts(processor_state);
+}
+
+/* MIV_I2C_isr()
+ * Please refer to miv_i2c.h for more info
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_state;
+ uint8_t i2c_ack_status;
+ uint8_t i2c_al_status;
+ uint8_t hold_bus;
+
+ /* Read the I2C master state */
+ i2c_state = this_i2c->master_state;
+
+ /* Read the ack and al status */
+ i2c_ack_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_RXACK);
+ i2c_al_status = HAL_get_8bit_reg_field(this_i2c->base_addr, STAT_AL);
+
+ switch (i2c_state)
+ {
+ /* I2C ISR State Machine
+ *
+ * Cases:
+ * - Transmit start condition and control byte
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Transmit data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Received NACK
+ * - Bus arbitration lost
+ *
+ * - Receive data
+ * - Received ACK and bus arbitration was not lost (Read or Write)
+ * - Bus arbitration lost
+ */
+
+ case MIV_I2C_TX_STA_CB:
+
+ /* Received ACK from target and I2C bus arbitration is not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ /* If I2C master write operation */
+ if (this_i2c->dir == MIV_I2C_WRITE_DIR)
+ {
+ /* write first byte of data and set the WR bit to transfer the data */
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+ /* Master read operation */
+ else
+ {
+ if (this_i2c->master_rx_size == 1u)
+ {
+ /* Send the ACK if the rx size is 1, transmit NACK to slave
+ * after receiving 1 byte to indicate slave to stop sending
+ * the data
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ /* Send the RD command to slave */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_rx_idx++;
+
+ /* Change state to receive data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+ }
+ else if (i2c_ack_status == 1u)
+ {
+ if (this_i2c->ack_polling_options == MIV_I2C_ACK_POLLING_ENABLE)
+ {
+ /* Target responded with NACK and ACK polling option is enabled
+ *
+ * Re-send the start condition and control byte
+ *
+ * TO-DO: This might become infinite loop check for timeout
+ * options.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ else
+ {
+ /* Target responded with NACK and ACK polling is disabled
+ * Abort the transaction and move to IDLE state
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Transmit master data */
+ case MIV_I2C_TX_DATA:
+
+ /* ACK received and arbitration was not lost */
+ if (i2c_ack_status == 0u && i2c_al_status == 0u)
+ {
+ uint8_t tx_buff[this_i2c->master_tx_size];
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_addr, TRANSMIT,
+ this_i2c->master_tx_buffer[this_i2c->master_tx_idx]);
+
+ tx_buff[this_i2c->master_tx_idx] = this_i2c->master_tx_buffer[this_i2c->master_tx_idx];
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ /* Increment the index */
+ this_i2c->master_tx_idx++;
+
+ /* Set the master state to TX data */
+ this_i2c->master_state = MIV_I2C_TX_DATA;
+ }
+
+ /* All the bytes are transmitted */
+ else if (this_i2c->master_tx_idx == this_i2c->master_tx_size)
+ {
+ /* If this is a MASTER_READ_TRANSACTION, hold bus and start a
+ new transfer in read mode now that the read address has been
+ written to the slave */
+ if(this_i2c->transaction == MIV_I2C_MASTER_READ_TRANSACTION)
+
+ {
+ //Switch direction to READ
+ this_i2c->dir = MIV_I2C_READ_DIR;
+
+ // Set the STA bit
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ /* Set the DIR bit and target addr */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, MIV_I2C_READ_DIR);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR, this_i2c->target_addr);
+
+ /* Set the WR bit to transmit the start condition and command byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01u);
+
+ // Reset the buffer index
+ this_i2c->master_tx_idx = 0u;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set the master state to RX data */
+ this_i2c->master_state = MIV_I2C_RX_DATA;
+ }
+
+ else
+ {
+ /* If releasing the bus, transmit the stop condition at the end
+ * of the transfer.
+ */
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+ }
+
+ else if (i2c_ack_status == 1u)
+ {
+ /* Received NACK from target device
+ *
+ * Release the bus and end the transfer
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+
+ this_i2c->master_status = MIV_I2C_FAILED;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+
+ /* Receive target device data */
+ case MIV_I2C_RX_DATA:
+
+ if (i2c_al_status == 0u)
+ {
+ if (this_i2c->master_rx_idx < this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1u] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ /* If next byte is last one
+ * Send NACK to target device to stop sending data
+ */
+ if (this_i2c->master_rx_idx == (this_i2c->master_rx_size - 1u))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x01u);
+ }
+
+ else
+ {
+ /* Send ACK to receive next bytes */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_ACK, 0x00u);
+ }
+
+ /* Set RD bit to receive next byte */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_RD, 0x01u);
+
+ this_i2c->master_rx_idx++;
+ }
+
+ /* Received all bytes */
+ else //if (this_i2c->master_rx_idx == this_i2c->master_rx_size)
+ {
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx - 1] =
+ HAL_get_8bit_reg(this_i2c->base_addr, RECEIVE);
+
+ hold_bus = this_i2c->bus_status & MIV_I2C_HOLD_BUS;
+
+ if (hold_bus == 0)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STO, 0x01u);
+ }
+ else
+ {
+ MIV_I2C_disable_irq();
+ }
+ this_i2c->master_status = MIV_I2C_SUCCESS;
+ this_i2c->transaction = MIV_I2C_NO_TRANSACTION;
+
+ this_i2c->master_state = MIV_I2C_IDLE;
+ }
+ }
+
+ else if (i2c_al_status == 1u)
+ {
+ /* Arbitration was lost on the BUS during the transmission of
+ * previous start condition and control byte.
+ * Re-send the STA and CB
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_TARGET_ADDR,
+ this_i2c->target_addr);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, TX_DIR, this_i2c->dir);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_STA, 0x01u);
+
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_WR, 0x01);
+
+ this_i2c->master_state = MIV_I2C_TX_STA_CB;
+ }
+
+ break;
+ }
+
+ /* Toggle the IACK bit to clear interrupt */
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_addr, CMD_IACK, 0x00u);
+}
+
+/*
+ * Please refer to miv_i2c.h for more info
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+)
+{
+ uint8_t i2c_status;
+
+ i2c_status = HAL_get_8bit_reg(this_i2c->base_addr, STATUS);
+
+ return i2c_status;
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
new file mode 100644
index 0000000..c5e704d
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c.h
@@ -0,0 +1,854 @@
+/*******************************************************************************
+ * 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
+ * I2C module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V I2C Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V I2C driver provides a set of functions for controlling the Mi-V I2C
+ Soft-IP module. This module is delivered as a part of the Mi-V Extended
+ Sub System(MIV_ESS). The driver provides a minimal APB-driven I2C interface,
+ supporting initiator read and write access to peripheral I2C devices.
+
+ The major features provided by the Mi-V I2C driver are:
+ - Support for configuring the I2C instance.
+ - I2C master operations.
+ - I2C ISR.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize and configure the Mi-V I2C through
+ the call to the MIV_I2C_init() and MIV_I2C_config() function for Mi-V I2C
+ instance in the design. The configuration parameter include base address and
+ Prescaler value.
+
+ ------------------------------
+ Interrupt Control
+ ------------------------------
+ The Mi-V I2C driver has to enable and disable the generation of interrupts by
+ Mi-V I2C at various times while operating. This enabling and disabling of the
+ interrupts must be done through the Mi-V RV32 HAL provided interrupt handlers.
+ For that reason, the method controlling the Mi-V I2C interrupts is system
+ specific and it is necessary to customize the MIV_I2C_enable_irq() and
+ MIV_I2C_disable_irq() functions as per requirement.
+
+ The implementation of MIV_I2C_enable_irq() should permit the interrupts
+ generated by the Mi-V I2C to the processor through a call to respective miv-hal
+ interrupt handler. The implementation of MIV_I2C_disable_irq() should prevent
+ the interrupts generated by a Mi-V I2C from interrupting the processor.
+ Please refer to the miv_i2c_interrupt.c for more information about the
+ implementation.
+
+ No MIV_I2C hardware configuration parameters are used by the driver, apart
+ from the MIV_I2C base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The Mi-V I2C software driver is designed to allow the control of multiple
+ instances of Mi-V I2C. Each instance of Mi-V I2C in the hardware design is
+ associated with a single instance of the miv_i2c_instance_t structure in the
+ software. User must allocate memory for one unique miv_i2c_instance_t
+ structure for each instance of Mi-V I2C in the hardware.
+ A pointer to the structure is passed to the subsequent driver functions in
+ order to identify the MIV_I2C hardware instance and to perform requested
+ operation.
+
+ Note: Do not attempt to directly manipulate the contents of the
+ miv_i2c_instance_t structure. These structures are only intended to be modified
+ by the driver functions.
+
+ The Mi-V I2C driver functions are grouped into following categories:
+ - Initialization and configuration
+ - I2C master operation functions to handle write, read and write_read
+ operations.
+ - Interrupt control
+
+ --------------------------------
+ Initialization and configuration
+ --------------------------------
+ The Mi-V I2C device is first initialized by the call to MIV_I2C_init(). This
+ function initializes the instance of Mi-V I2C with the base address.
+ MIV_I2C_init() function must be called before any other Mi-V I2C driver API.
+
+ The configuration of the Mi-V I2C instance is done via call to the
+ MIV_I2C_config() function. This function will set the prescale value which is
+ used to set the frequency of the I2C clock(SCLK) generated by I2C module.
+
+ ---------------------------------
+ Transaction types
+ ---------------------------------
+ The driver is designed to handle three types of transactions:
+ - Write transactions
+ - Read transactions
+ - Write-Read transaction
+
+ ### Write Transaction
+ The write transaction begins with master sending a start condition, followed
+ by device address byte with the R/W bit set to logic '0', and then by the
+ word address bytes. The slave acknowledges the receipt of its address with
+ acknowledge bit. The master sends one byte at a time to the slave, which must
+ acknowledge the receipt of each byte for the next byte to be sent. The master
+ sends STOP condition to complete the transaction. The slave can abort the
+ transaction by replying with negative acknowledge.
+
+ The application programmer can choose not to send the STOP bit at the end of
+ the transaction causing repetitive start conditions.
+
+ ### Read Transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The start condition is followed by the
+ control byte which contains 7-bit slave address followed by R/W bit set to
+ logic '1'. The slave sends data one byte at a time to the master, which must
+ acknowledge receipt of each byte for the next byte to be sent. The master
+ sends a non-acknowledge bit following the last byte it wishes to read
+ followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ ### Write-Read Transaction
+ The write read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP condition sent
+ between the write and read phase of write-read transaction. A repeated START
+ condition is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send an memory/register
+ address in the write transaction specifying the start address of the data to
+ be transferred during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ -------------------------------------
+ Interrupt Control
+ -------------------------------------
+ The Mi-V I2C driver is interrupt driven and it uses the MIV_I2C_irq() function
+ to drive the ISR state machine which is at the heart of the driver. The
+ application is responsible for providing the link between the interrupt
+ generating hardware and the Mi-V I2C interrupt handler and must ensure that
+ the MIV_I2C_isr() function is called with the correct miv_i2c_instance_t
+ structure pointer for the Mi-V I2C instance initiating the interrupt.
+
+*//*=========================================================================*/
+#ifndef MIV_I2C_H_
+#define MIV_I2C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "miv_i2c_regs.h"
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#else
+#include "hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The miv_i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum miv_i2c_status
+{
+ MIV_I2C_SUCCESS = 0u,
+ MIV_I2C_IN_PROGRESS,
+ MIV_I2C_FAILED,
+ MIV_I2C_TIMED_OUT
+}miv_i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ This structure is used to identify the MIV_I2C hardware instances in a system.
+ Your application software should declare one instance of this structure for
+ each instance of the MIV_I2C in your system. The function MIV_I2C_init()
+ Initializes this structure. A pointer to an initialised instance of the structure
+ should be passed as the first parameter to the MIV_I2C driver functions, to
+ identify which MIV_I2C hardware instance should perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the MIV_I2C driver. Software using the MIV_I2C driver should only need to
+ create one single instance of this data structure for each MIV_I2C hardware
+ instance in the system, then pass a pointer to these data structures with each
+ call to the MIV_I2C driver in order to identify the MIV_I2C hardware instance
+ it wishes to use.
+*/
+
+typedef struct miv_i2c_instance
+{
+ addr_t base_addr;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type */
+ uint8_t transaction;
+
+ uint8_t bus_options;
+
+ uint8_t ack_polling_options;
+
+ /* Current State of the I2C master */
+ uint8_t master_state;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile miv_i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+
+}miv_i2c_instance_t;
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_RELEASE_BUS
+ =====================
+ The MIV_I2C_RELEASE_BUS constant is used to specify the bus_options parameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define MIV_I2C_RELEASE_BUS 0x00u
+
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_HOLD_BUS
+ =====================
+ The MIV_I2C_HOLD_BUS constant is used to specify the bus_optionsparameter
+ for MIV_I2C_read(), MIV_I2C_write() and MIV_I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define MIV_I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_DISABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_DISABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). Acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling disabled, if the target slave device responds to the
+ control byte with a NACK, the MIV_I2C will abort the transfer.
+ */
+#define MIV_I2C_ACK_POLLING_DISABLE 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_I2C_ACK_POLLING_ENABLE
+ =====================
+ The MIV_I2C_ACK_POLLING_ENABLE constant is used to specify the
+ ack_polling_options parameter to functions MIV_I2C_write(),
+ MIV_I2C_write_read() and MIV_I2C_read(). acknowledgment polling is used when
+ working with I2C memory devices such as EEPROM, which feature an internal
+ write cycle.
+
+ With acknowledgment polling enabled, if the slave device responds to the
+ control byte with a NACK, the MIV_I2C will repeatedly transmit another control
+ byte until the slave device accepts the connection with an ACK, or the timeout
+ specified in the MIV_I2C_wait_complete() function is reached. Acknowledgment
+ polling allows for the next read/write operation to be started as soon as the
+ EEPROM has completed its internal write cycle.
+ */
+#define MIV_I2C_ACK_POLLING_ENABLE 0x01u
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_init() function is used to initialize the Mi-V I2C module instance
+ with the base address.
+
+ Note: This function should be called before calling any other Mi-V I2C
+ functions.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @param base_addr
+ Base address of the Mi-V I2C module instance in the MIV_ESS
+ soft IP.
+
+ @return
+ This function does not return any value.
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+ }
+ @endcode
+ */
+void
+MIV_I2C_init
+(
+ miv_i2c_instance_t *this_i2c,
+ addr_t base_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_config() function is used to configure the Mi-V I2C module. This
+ function will set the prescale value which is used to set the frequency of
+ the I2C clock(SCLK) generated by I2C module and also enables the I2C core and
+ interrupts.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param clk_prescale
+ The value used to set the frequency of Mi-V I2C serial clock
+ (SCLK) generated by the Mi-V I2C module instance. The
+ prescaler value required to set particular frequency of
+ Mi-V I2C can be calculated using following formula:
+
+ prescaler = (System Clock Frequency) / (5 * (Desired I2C Clock Frequency)) - 1
+
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+ }
+ @endcode
+ */
+void
+MIV_I2C_config
+(
+ miv_i2c_instance_t *this_i2c,
+ uint16_t clk_prescale
+);
+
+
+uint8_t
+MIV_I2C_start
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+
+uint8_t
+MIV_I2C_stop
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write() is used to set up and start the Mi-V I2C master write
+ transaction. This function is used for all Mi-V master write operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the write
+ buffer should not be freed or should not go out of scope before the write
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_read() is used to set up and start the Mi-V I2C master read
+ transaction. This function is used for all MIV_I2C master read operation.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the read buffer passed as parameter should not be modified until the write
+ transaction completes. It also means that the memory allocated for the read
+ buffer should not be freed or should not go out of scope before the read
+ completes.
+ You can check for the write transaction completion by polling the master_status
+ from miv_i2c_instance_t structure as shown in the sample code.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ MIV_I2C_read (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t i2c_target_addr,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_write_read() is used to set up and start the Mi-V I2C master
+ write_read transaction. This function is used for all MIV_I2C master write_read
+ operation.
+
+ This function is used in cases where data is being requested from a specific
+ address offset inside the target I2C slave device.
+ In this type of I2C operation, the I2C master starts by initiating a write
+ operation. During this write operation, the specific address offset is written
+ to the I2C slave. Once the address offset has been written to the I2C slave,
+ the I2C master transmits a repeated start, and initiates a read operation to
+ read data from the set address.
+
+ For more information about the operation, please refer to the 'theory of
+ operations' section at the start of this document.
+
+ This function returns immediately after initiating the transaction. The content
+ of the write and read buffer passed as parameter should not be modified until
+ the write transaction completes. It also means that the memory allocated for
+ the write and read buffer should not be freed or should not go out of scope
+ before the operation completes.
+ You can check for the write_read transaction completion by polling the
+ master_status from miv_i2c_instance_t structure.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+
+ @param i2c_target_addr
+ This parameter specifies the serial address for the slave
+ device.
+
+ @param write_buffer
+ This parameter is a pointer to the buffer holding data to be
+ written to target I2C device.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param write_size
+ Number of bytes held in the write_buffer to be written to the
+ I2C device.
+
+ @param read_buffer
+ This parameter is a pointer to the buffer where the data
+ received from the I2C slave device is stored.
+ Care must be taken not to release the memory used by this
+ buffer before the write transaction completes.
+
+ @param read_size
+ Number of bytes held in the write_buffer to be read from the
+ I2C device.
+
+ @param bus_options:
+ The bus_options parameter is used to indicate if the I2C bus
+ should be released on completion of the write transaction.
+ Using the MIV_I2C_RELEASE_BUS constant for the bus_options
+ parameter causes a STOP bit to be generated at the end of the
+ write transaction causing the bus to be released for other I2C
+ devices to use. Using the MIV_I2C_HOLD_BUS constant as
+ bus_options parameter prevents a STOP bit from being generated
+ at the end of the write transaction, preventing other I2C
+ devices from initiating a bus transaction.
+
+ @param ack_polling_options:
+ The ack_polling_options parameter is used to indicate how the
+ MIV_I2C will respond if the slave device transmits a NACK to
+ the I2C control byte. Using the MIV_I2C_ACK_POLLING_DISABLE
+ constant for the ack_polling_options parameter causes the
+ MIV_I2C to abort the transfer if the slave device responds to
+ the I2C control byte with a NACK. Using the
+ MIV_I2C_ACK_POLLING_ENABLE constant for the ack_polling_options
+ parameter causes the MIV_I2C to repeatedly transmit a control
+ byte to the slave device until the slave device responds with
+ an ACK or the timeout specified in the MIV_I2C_wait_complete()
+ function is reached.
+ @return
+ This function does not return any value.
+
+
+ Example:
+ @code
+ #define MIV_I2C_BASE_ADDR 0x7A000000u
+
+ miv_i2c_instance_t g_miv_i2c_inst;
+
+ void main( void )
+ {
+ MIV_I2C_init( &g_miv_i2c_inst, MIV_I2C_BASE_ADDR);
+
+ Configuring Mi-V I2C core at Normal Speed (100MHz) for 50MHz Sys clock.
+ MIV_I2C_config(&g_miv_i2c_inst, 0x63);
+
+ MIV_I2C_write (&g_miv_i2c_inst,
+ DUALEE_SLAVEADDRESS_1,
+ i2c_tx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+
+ // reset miv_i2c_status variable
+ miv_i2c_status = 0u;
+
+ uint8_t addr_offset[2] = {0x00, 0x00};
+ MIV_I2C_write_read(&miv_i2c,
+ DUALEE_SLAVEADDRESS_1,
+ addr_offset,
+ sizeof(addr_offset),
+ i2c_rx_buffer,
+ transfer_size,
+ MIV_I2C_RELEASE_BUS,
+ MIV_I2C_ACK_POLLING_ENABLE
+ );
+
+ // Wait till the miv i2c status changes
+ do {
+ miv_i2c_status = miv_i2c.master_status;
+ }while (MIV_I2C_IN_PROGRESS == miv_i2c_status);
+ }
+ @endcode
+ */
+void
+MIV_I2C_write_read
+(
+ miv_i2c_instance_t *this_i2c,
+ uint8_t target_addr,
+ const uint8_t *write_buffer,
+ uint16_t write_size,
+ uint8_t *read_buffer,
+ uint16_t read_size,
+ uint8_t bus_options,
+ uint8_t ack_polling_options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_isr() function contains the MIV_I2C's interrupt service routine.
+ This ISR is at the heart of the MIV_I2C driver, and is used to control the
+ interrupt-driven, byte-by-byte I2C read and write operations.
+
+ The ISR operates as a Finite State Machine (FSM), which uses the previously
+ completed I2C operation and its result to determine which I2C operation will
+ be performed next.
+
+ The ISR operation is divided into following categories:
+ - MIV_I2C_IDLE
+ - MIV_I2C_TX_STA_CB
+ - MIV_I2C_TX_DATA
+ - MIV_I2C_RX_DATA
+
+ ##### MIV_I2C_IDLE
+ The MIV_I2C_IDLE is entered on reset, or when an I2C master operation has been
+ completed or aborted.
+ Upon entering, the FSM will remain in this state until a write, read, or
+ write-read operation is requested
+
+ ##### MIV_I2C_STA_CB
+ The MIV_I2C_TX_STA_CB operation is performed when the start condition and
+ control byte(i2c target address(7-bit) and direction of transaction(1-bit)) is
+ transmitted by the Mi-V I2C master device to the slave.
+ If the target I2C slave device responded to the previous START Condition +
+ Control Byte with an ACK, the MIV_I2C will start the requested I2C
+ read/write operation.
+ If the target slave I2C slave device responds with NACK, the MIV_I2C will
+ remain in this state or return to the idle state based on ack_polling
+ configuration.
+
+ ##### MIV_I2C_TX_DATA
+ The MIV_I2C_TX_DATA state is entered after the target slave device accepts a
+ write request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C write operations.
+ The FSM will remain in this state until either all data bytes have been
+ written to the target slave device, or an error occurs during the write
+ operation.
+
+ ##### MIV_I2C_RX_DATA
+ The MIV_I2C_RX_DATA state is entered after the target slave device accepts a
+ read request with an ACK.
+ This state is used to handle the byte-by-byte MIV_I2C read operations.
+ The FSM will remain in this state until either all data bytes have been
+ received from the target slave device, or an error occurs.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ */
+void
+MIV_I2C_isr
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MIV_I2C_get_status() returns the 8-bit Mi-V I2C status register value.
+
+ @param this_i2c
+ A pointer to the miv_i2c_instance_t data structure which
+ will hold all the data related to the Mi-V I2C module
+ instance being used. A pointer to this structure is passed to
+ rest of the Mi-V I2C driver functions for operation.
+ @return
+ This function returns 8-bit Mi-V I2C status register value.
+ */
+uint8_t
+MIV_I2C_get_status
+(
+ miv_i2c_instance_t *this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
new file mode 100644
index 0000000..871eafe
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_interrupt.c
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains functions used for MIV_I2C driver interrupt control.
+ * User should enable and disable the interrupts according to their design.
+ * Please refer to miv_i2c.h file for more information.
+ */
+
+#include "miv_rv32_hal/miv_rv32_hal.h"
+
+void MIV_I2C_disable_irq(void)
+{
+/* Disable I2C interrupt */
+ MRV_disable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+void MIV_I2C_enable_irq(void)
+{
+/* Enable I2C interrupt */
+ MRV_enable_local_irq(MRV32_MSYS_EIE2_IRQn);
+}
+
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
new file mode 100644
index 0000000..9a4bfbf
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_i2c/miv_i2c_regs.h
@@ -0,0 +1,158 @@
+ /*******************************************************************************
+ * 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 I2C module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_I2C_APB_REGISTERS
+#define MIV_I2C_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * Prescale register details
+ */
+#define PRESCALE_REG_OFFSET 0x00u
+
+/* Prescale register bits */
+#define PRESCALE_OFFSET 0x00u
+#define PRESCALE_MASK 0xFFFFu
+#define PRESCALE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Control register details
+ */
+#define CONTROL_REG_OFFSET 0x04u
+
+/* Control register bits */
+#define CONTROL_OFFSET 0x04u
+#define CONTROL_MASK 0xC0u
+#define CONTROL_SHIFT 0u
+
+/* Control register Core Enable Bit */
+#define CTRL_CORE_EN_OFFSET 0x04u
+#define CTRL_CORE_EN_MASK 0x80u
+#define CTRL_CORE_EN_SHIFT 7u
+
+/* Control register IRQ Enable bit */
+#define CTRL_IRQ_EN_OFFSET 0x04u
+#define CTRL_IRQ_EN_MASK 0x40u
+#define CTRL_IRQ_EN_SHIFT 6u
+
+/*------------------------------------------------------------------------------
+ * Transmit register details
+ */
+#define TRANSMIT_REG_OFFSET 0x08u
+
+/* Transmit register bits */
+#define TRANSMIT_OFFSET 0x08u
+#define TRANSMIT_MASK 0xFFu
+#define TRANSMIT_SHIFT 0u
+
+/* Transmit register DIR bit */
+#define TX_DIR_OFFSET 0x08u
+#define TX_DIR_MASK 0x01u
+#define TX_DIR_SHIFT 0u
+
+/* Transmit register TARGET_ADDR bit */
+#define TX_TARGET_ADDR_OFFSET 0x08u
+#define TX_TARGET_ADDR_MASK 0xFEu
+#define TX_TARGET_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * Receive register details
+ */
+#define RECEIVE_REG_OFFSET 0x0Cu
+
+/* Receive register bits */
+#define RECEIVE_OFFSET 0x0Cu
+#define RECEIVE_MASK 0xFFu
+#define RECEIVE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * Command register details
+ */
+#define COMMAND_REG_OFFSET 0x10u
+
+/* Command register bits */
+#define COMMAND_OFFSET 0x10u
+#define COMMAND_MASK 0xF9u
+#define COMMAND_SHIFT 0u
+
+/* Command register IACK bit */
+#define CMD_IACK_OFFSET 0x10u
+#define CMD_IACK_MASK 0x01u
+#define CMD_IACK_SHIFT 0u
+
+/* Command register ACK bit */
+#define CMD_ACK_OFFSET 0x10u
+#define CMD_ACK_MASK 0x08u
+#define CMD_ACK_SHIFT 3u
+
+/* Command register WR bit */
+#define CMD_WR_OFFSET 0x10u
+#define CMD_WR_MASK 0x10u
+#define CMD_WR_SHIFT 4u
+
+/* Command register RD bit */
+#define CMD_RD_OFFSET 0x10u
+#define CMD_RD_MASK 0x20u
+#define CMD_RD_SHIFT 5u
+
+/* Command register STO bit */
+#define CMD_STO_OFFSET 0x10u
+#define CMD_STO_MASK 0x40u
+#define CMD_STO_SHIFT 6u
+
+/* Command register STA bit */
+#define CMD_STA_OFFSET 0x10u
+#define CMD_STA_MASK 0x80u
+#define CMD_STA_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * Status register details
+ */
+#define STATUS_REG_OFFSET 0x14u
+
+/* Command register bits */
+#define STATUS_OFFSET 0x14u
+#define STATUS_MASK 0xFFu
+#define STATUS_SHIFT 0u
+
+/* Status register Interrupt Flag(IF) bit */
+#define STAT_IF_OFFSET 0x14u
+#define STAT_IF_MASK 0x01u
+#define STAT_IF_SHIFT 0u
+
+/* Status register Transfer in Progress(TIP) bit */
+#define STAT_TIP_OFFSET 0x14u
+#define STAT_TIP_MASK 0x02u
+#define STAT_TIP_SHIFT 1u
+
+/* Status register Arbitration Lost(AL) bit */
+#define STAT_AL_OFFSET 0x14u
+#define STAT_AL_MASK 0x20u
+#define STAT_AL_SHIFT 5u
+
+/* Status register Busy(BUSY) bit */
+#define STAT_BUSY_OFFSET 0x14u
+#define STAT_BUSY_MASK 0x40u
+#define STAT_BUSY_SHIFT 6u
+
+/* Status register Ack received(RXACK) bit */
+#define STAT_RXACK_OFFSET 0x14u
+#define STAT_RXACK_MASK 0x80u
+#define STAT_RXACK_SHIFT 7u
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_I2C_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
new file mode 100644
index 0000000..903f029
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.c
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MI-V Soft IP fabric bare-metal driver for Mi-V PLIC module. This module is
+ * delivered as a part of Mi-V Extended Sub System(MIV_ESS).
+ * Please refer to miv_plic.h file for more information.
+ */
+
+#include "miv_plic.h"
+
+/***************************************************************************//**
+ * Mi-V PLIC interrupt handler function declaration.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t MIV_PLIC_EXT0_IRQHandler(void);
+uint8_t MIV_PLIC_EXT1_IRQHandler(void);
+uint8_t MIV_PLIC_EXT2_IRQHandler(void);
+uint8_t MIV_PLIC_EXT3_IRQHandler(void);
+uint8_t MIV_PLIC_EXT4_IRQHandler(void);
+uint8_t MIV_PLIC_EXT5_IRQHandler(void);
+uint8_t MIV_PLIC_EXT6_IRQHandler(void);
+uint8_t MIV_PLIC_EXT7_IRQHandler(void);
+uint8_t MIV_PLIC_EXT8_IRQHandler(void);
+uint8_t MIV_PLIC_EXT9_IRQHandler(void);
+uint8_t MIV_PLIC_EXT10_IRQHandler(void);
+uint8_t MIV_PLIC_EXT11_IRQHandler(void);
+uint8_t MIV_PLIC_EXT12_IRQHandler(void);
+uint8_t MIV_PLIC_EXT13_IRQHandler(void);
+uint8_t MIV_PLIC_EXT14_IRQHandler(void);
+uint8_t MIV_PLIC_EXT15_IRQHandler(void);
+uint8_t MIV_PLIC_EXT16_IRQHandler(void);
+uint8_t MIV_PLIC_EXT17_IRQHandler(void);
+uint8_t MIV_PLIC_EXT18_IRQHandler(void);
+uint8_t MIV_PLIC_EXT19_IRQHandler(void);
+uint8_t MIV_PLIC_EXT20_IRQHandler(void);
+uint8_t MIV_PLIC_EXT21_IRQHandler(void);
+uint8_t MIV_PLIC_EXT22_IRQHandler(void);
+uint8_t MIV_PLIC_EXT23_IRQHandler(void);
+uint8_t MIV_PLIC_EXT24_IRQHandler(void);
+uint8_t MIV_PLIC_EXT25_IRQHandler(void);
+uint8_t MIV_PLIC_EXT26_IRQHandler(void);
+uint8_t MIV_PLIC_EXT27_IRQHandler(void);
+uint8_t MIV_PLIC_EXT28_IRQHandler(void);
+uint8_t MIV_PLIC_EXT29_IRQHandler(void);
+uint8_t MIV_PLIC_EXT30_IRQHandler(void);
+
+/***************************************************************************//**
+ * MIV_PLIC interrupt handler for external interrupts.
+ * The array of the function pointers pointing to the weak handler of the Mi-V
+ * PLIC interrupt handlers.
+ * These functions are called by the external interrupt handler of the MIV_RV32
+ * core base on the PLIC source causing the interrupt.
+ */
+uint8_t (* const ext_irq_handler_table[32]) (void) =
+{
+ Invalid_IRQHandler,
+ MIV_PLIC_EXT0_IRQHandler,
+ MIV_PLIC_EXT1_IRQHandler,
+ MIV_PLIC_EXT2_IRQHandler,
+ MIV_PLIC_EXT3_IRQHandler,
+ MIV_PLIC_EXT4_IRQHandler,
+ MIV_PLIC_EXT5_IRQHandler,
+ MIV_PLIC_EXT6_IRQHandler,
+ MIV_PLIC_EXT7_IRQHandler,
+ MIV_PLIC_EXT8_IRQHandler,
+ MIV_PLIC_EXT9_IRQHandler,
+ MIV_PLIC_EXT10_IRQHandler,
+ MIV_PLIC_EXT11_IRQHandler,
+ MIV_PLIC_EXT12_IRQHandler,
+ MIV_PLIC_EXT13_IRQHandler,
+ MIV_PLIC_EXT14_IRQHandler,
+ MIV_PLIC_EXT15_IRQHandler,
+ MIV_PLIC_EXT16_IRQHandler,
+ MIV_PLIC_EXT17_IRQHandler,
+ MIV_PLIC_EXT18_IRQHandler,
+ MIV_PLIC_EXT19_IRQHandler,
+ MIV_PLIC_EXT20_IRQHandler,
+ MIV_PLIC_EXT21_IRQHandler,
+ MIV_PLIC_EXT22_IRQHandler,
+ MIV_PLIC_EXT23_IRQHandler,
+ MIV_PLIC_EXT24_IRQHandler,
+ MIV_PLIC_EXT25_IRQHandler,
+ MIV_PLIC_EXT26_IRQHandler,
+ MIV_PLIC_EXT27_IRQHandler,
+ MIV_PLIC_EXT28_IRQHandler,
+ MIV_PLIC_EXT29_IRQHandler,
+ MIV_PLIC_EXT30_IRQHandler
+};
+
+/* Mi-V PLIC interrupt weak handlers */
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT1_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT2_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT3_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT4_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT5_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT6_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT7_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT8_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT9_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT10_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT11_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT12_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT13_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT14_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT15_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT16_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT17_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT18_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT19_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT20_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT21_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT22_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT23_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT24_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT25_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT26_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT27_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT28_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT29_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+__attribute__((weak)) uint8_t MIV_PLIC_EXT30_IRQHandler(void)
+{
+ return(0U); /* Default handler */
+}
+
+/*-------------------------------------------------------------------------*//**
+ * Please refer to miv_plic.h for more information about this function.
+*/
+void
+MIV_PLIC_isr
+(
+ miv_plic_instance_t *this_plic
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* claim the interrupt from PLIC controller */
+
+ uint32_t int_num = HAL_get_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE);
+
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+ disable = ext_irq_handler_table[int_num]();
+
+ /* Indicate the PLIC controller that the interrupt is processed and claim is
+ * complete. */
+ HAL_set_32bit_reg(this_plic->base_addr +
+ (0x1000 * hart_id), INT_CLAIM_COMPLETE, int_num);
+
+ if (EXT_IRQ_DISABLE == disable)
+ {
+ MIV_PLIC_disable_irq(this_plic, (miv_plic_irq_num_t)int_num);
+ }
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
new file mode 100644
index 0000000..f5d64cd
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic.h
@@ -0,0 +1,425 @@
+/*******************************************************************************
+ * 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
+ * PLIC module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(ESS).
+ */
+ /*=========================================================================*//**
+ @mainpage Mi-V PLIC Bare Metal Driver
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ The Mi-V driver provides a set of functions for controlling the Mi-V PLIC
+ (platform level interrupt controller) soft-IP module. This module is delivered
+ as a part of the MIV_ESS. The PLIC multiplexes external interrupt signals into
+ a single interrupt signal that is connected to an external interrupt of the
+ processor.
+
+ The major features provided by the driver are:
+ - Support for configuring the PLIC instances.
+ - Enabling and Disabling interrupts
+ - Interrupt Handling
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ ==============================================================================
+ Hardware Flow Dependencies
+ ==============================================================================
+ The application software should initialize the Mi-V PLIC through the call to
+ the MIV_PLIC_init() function for Mi-V PLIC instance in the design.
+
+ No Mi-V PLIC hardware configuration parameters are used by the driver, apart
+ from the Mi-V PLIC base address. Hence, no additional configuration files
+ are required to use the driver.
+
+ ==============================================================================
+ Theory of Operation
+ ==============================================================================
+ The operation of Mi-V PLIC driver is divided into following steps:
+ - Initialization
+ - Enabling and Disabling interrupts
+ - Interrupt control
+
+ --------------------------------------------
+ Initialization
+ --------------------------------------------
+ The Mi-V PLIC module is first initialized by the call to MIV_PLIC_init(). This
+ function takes a pointer to the Mi-V PLIC instance data structure and the base
+ address of the Mi-V PLIC instance is defined by the hardware design. The
+ instance data structure is used to store the base address of the Mi-V PLIC
+ module and a pointer to the Mi-V PLIC register data structure. The Mi-V PLIC
+ register data structure maps the address of the Mi-V PLIC registers.
+
+ ---------------------------------------------
+ Enabling and Disabling interrupts
+ ---------------------------------------------
+ The MIV_PLIC_enable_irq() function enables the specific interrupt provided by
+ user. A call to this function will allow the enabling of each of the global
+ interrupts corresponding to the bit in the interrupt enable register of Mi-V
+ PLIC.
+ The MIV_PLIC_disable_irq() function disables the specific interrupt provided
+ by the user. This function can be used to disable the interrupts from outside
+ of the external interrupt handler.
+
+ ----------------------------------------
+ Interrupt Control
+ ----------------------------------------
+ When an interrupt occurs on an enabled interrupt, the PLIC gateway captures
+ the interrupt and asserts the corresponding interrupt pending bit. Once
+ the enable bit and pending bit are asserted, then the PLIC_IRQ signal asserts
+ until the interrupt is claimed by the driver interrupt handler MIV_PLIC_irq()
+ function.
+ When multiple interrupts assert then the lowest interrupt number will be
+ serviced first, for example, if interrupt 1 and 6 assert at the same time,
+ interrupt 1 will be serviced first, followed by interrupt 6.
+
+*/
+
+#ifndef MIV_PLIC_H_
+#define MIV_PLIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include "miv_plic_regs.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "miv_rv32_hal/miv_rv32_hal.h"
+#else
+#include "hal.h"
+#include "miv_rv32_hal.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ This enumeration is used to select a specific Mi-V PLIC interrupt. It is
+ used as a parameter to enable or disable the interrupt.
+*/
+typedef enum miv_plic_irq_num
+{
+ NoInterrupt_IRQn = 0,
+ MIV_PLIC_EXT0_IRQn = 1,
+ MIV_PLIC_EXT1_IRQn = 2,
+ MIV_PLIC_EXT2_IRQn = 3,
+ MIV_PLIC_EXT3_IRQn = 4,
+ MIV_PLIC_EXT4_IRQn = 5,
+ MIV_PLIC_EXT5_IRQn = 6,
+ MIV_PLIC_EXT6_IRQn = 7,
+ MIV_PLIC_EXT7_IRQn = 8,
+ MIV_PLIC_EXT8_IRQn = 9,
+ MIV_PLIC_EXT9_IRQn = 10,
+ MIV_PLIC_EXT10_IRQn = 11,
+ MIV_PLIC_EXT11_IRQn = 12,
+ MIV_PLIC_EXT12_IRQn = 13,
+ MIV_PLIC_EXT13_IRQn = 14,
+ MIV_PLIC_EXT14_IRQn = 15,
+ MIV_PLIC_EXT15_IRQn = 16,
+ MIV_PLIC_EXT16_IRQn = 17,
+ MIV_PLIC_EXT17_IRQn = 18,
+ MIV_PLIC_EXT18_IRQn = 19,
+ MIV_PLIC_EXT19_IRQn = 20,
+ MIV_PLIC_EXT20_IRQn = 21,
+ MIV_PLIC_EXT21_IRQn = 22,
+ MIV_PLIC_EXT22_IRQn = 23,
+ MIV_PLIC_EXT23_IRQn = 24,
+ MIV_PLIC_EXT24_IRQn = 25,
+ MIV_PLIC_EXT25_IRQn = 26,
+ MIV_PLIC_EXT26_IRQn = 27,
+ MIV_PLIC_EXT27_IRQn = 28,
+ MIV_PLIC_EXT28_IRQn = 29,
+ MIV_PLIC_EXT29_IRQn = 30,
+ MIV_PLIC_EXT30_IRQn = 31
+} miv_plic_irq_num_t;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the priority threshold and claim complete register in
+ * the memory.
+ */
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+/*--------------------------------------------------------------------------*//*
+ * This structure maps the Interrupt enable sources from 0 - 1023 for one
+ * context.
+ */
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V PLIC module. This structure
+ is used by all the functions to access the Mi-V PLIC registers.
+*/
+typedef struct miv_plic_instance
+{
+ addr_t base_addr;
+} miv_plic_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_isr is the top level interrupt handler function for the Mi-V PLIC
+ * driver. You must call the MIV_PLIC_isr() from the system level interrupt
+ * handler(External_IRQHandler).
+ * This function must be called from the external interrupt handler function
+ * provided by the processor hardware abstraction layer. In case of MIV_RV32
+ * soft processor, it must be called from External_IRQHandler() function
+ * provided by MIV_RV32 HAL.
+ *
+ * The MIV_PLIC_isr() function claims the interrupt number
+ * that triggered the interrupt and then invokes the appropriate PLIC interrupt
+ * handler.
+ * After handling the PLIC interrupt, this function will complete the interrupt
+ * by clearing the claim complete bit for the particular interrupt source.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example:
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ * uint8_t MIV_PLIC_EXT0_IRQHandler(void)
+ * {
+ * *** ISR operation ***
+ *
+ * return(EXT_IRQ_KEEP_ENABLED);
+ * }
+ *
+ * void External_IRQHandler(void)
+ * {
+ * uint32_t reg_val = read_csr(mip);
+ * MIV_PLIC_isr(&g_plic);
+ * }
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+void MIV_PLIC_isr(miv_plic_instance_t *this_plic);
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_init() function initializes the Mi-V PLIC instance with base
+ * address. This function resets the PLIC controller by disabling all the PLIC
+ * interrupts.
+ *
+ * Note: This function must be called before calling any other Mi-V PLIC driver
+ * function.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ *
+ * @param base_addr
+ * Base address of the Mi-V PLIC instance in the MIV_ESS soft-IP.
+ *
+ * @param ext_intr_sources
+ * Number of interrupts initialized in the design.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_init
+(
+ miv_plic_instance_t *this_plic,
+ addr_t base_addr,
+ uint8_t ext_intr_sources
+)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ this_plic->base_addr = base_addr;
+
+ /* Disable all interrupts for the current hart.
+ * The PLIC_EXT_INTR_SOURCES should be defined in the hw_platform.h. This
+ * macro holds the number of PLIC interrupts enabled in the design.
+ */
+ for(inc = 0; inc < ((ext_intr_sources + 32u) / 32u); ++inc)
+ {
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + inc + (hart_id * 128)), INT_ENABLE , 0x0u);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_enable_irq() function enables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to enable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_enable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current |= (uint32_t)1 << (IRQn % 32);
+
+ HAL_set_32bit_reg(
+ (this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+/*-------------------------------------------------------------------------*//**
+ * The MIV_PLIC_disable_irq() function disables the PLIC interrupt provided with
+ * IRQn parameter.
+ *
+ * NOTE:
+ * This function can be used to disable the PLIC interrupt from outside the
+ * external interrupt handler functions.
+ * If you wish to disable the PLIC interrupt from the external interrupt handler,
+ * you should use the return value of EXT_IRQ_DISABLE. This will disable the
+ * selected PLIC interrupt from the Mi-V PLIC driver interrupt handler.
+ *
+ * @param this_plic
+ * A pointer to the miv_plic_instance_t data structure which
+ * will hold all the data related to the Mi-V PLIC instance
+ * being used. A pointer to this data structure is passed to
+ * rest of Mi-V PLIC driver functions for operation.
+ * @param IRQn
+ * Number of PLIC interrupt to disable.
+ *
+ * @return
+ * This function does not return any value.
+ *
+ * Example
+ * @code
+ * #define MIV_PLIC_BASE_ADDR 0x70000000
+ * #define PLIC_EXT_INTR_SOURCES 31
+ *
+ * miv_plic_instance_t g_plic;
+ *
+ * void main(void)
+ * {
+ * MIV_PLIC_init(&g_plic, MIV_PLIC_BASE_ADDR, PLIC_EXT_INTR_SOURCES);
+ *
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_enable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ *
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT0_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT1_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT2_IRQn);
+ * MIV_PLIC_disable_irq(&g_plic, MIV_PLIC_EXT3_IRQn);
+ * }
+ * @endcode
+ */
+static inline void
+MIV_PLIC_disable_irq
+(
+ miv_plic_instance_t *this_plic,
+ miv_plic_irq_num_t IRQn
+)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ uint32_t current = HAL_get_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)) , INT_ENABLE);
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ HAL_set_32bit_reg((this_plic->base_addr + (IRQn/32) + (hart_id * 128)), INT_ENABLE, current);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
new file mode 100644
index 0000000..76cbc0b
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_plic/miv_plic_regs.h
@@ -0,0 +1,31 @@
+ /*******************************************************************************
+ * 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 PLIC module driver. This module is delivered as a part of Mi-V extended
+ * Sub-System(MIV_ESS).
+ */
+
+#ifndef MIV_PLIC_REGISTERS
+#define MIV_PLIC_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Interrupt pending register offset */
+#define INT_PENDING_REG_OFFSET 0x1000u
+
+/* Interrupt enable register */
+#define INT_ENABLE_REG_OFFSET 0x2000u
+
+/* Interrupt claim complete register */
+#define INT_CLAIM_COMPLETE_REG_OFFSET 0x200004u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_PLIC_REGISTERS */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
new file mode 100644
index 0000000..5f00889
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_timer/miv_timer.h
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * 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.
+ *
+ * Mi-V Timer Soft IP bare-metal driver. This module is delivered as part of
+ * the Mi-V Extended Sub System(ESS) MIV_ESS.
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V Timer Bare Metal Driver.
+ The Mi-V Timer bare metal software driver supports the timer module which
+ serves as a system timer for the Mi-V Extended Sub System(ESS).
+
+ @section intro_sec Introduction
+ The MI-V Timer driver supports set of functions for controlling the Mi-V
+ Timer module.
+ The Mi-V Timer can generate a timer interrupt signal for the system based on
+ special system clock intervals specified by the parameters that can be passed
+ in by the user.
+
+ The major features provided by Mi-V Timer driver are:
+ - Support for Mi-V Timer instance for each Mi-V Timer peripheral.
+ - Read current time
+ - Write to the machine time compare register
+
+ @section hw_dependencies Hardware Flow dependency
+ The application should configure the Mi-V Timer driver through calls to
+ MIV_TIMER_init() functions for each MIV_TIMER instance in the hardware
+ design. The configuration parameter include the MIV_TIMER hardware instance,
+ base address and number of ticks to generate timer interrupt.
+
+ MIV_RV32 core offers flexibility in terms of generating the MTIME and MTIMECMP
+ registers internal to the core or using external time reference.
+ When MIV_ESS is interfaced with MIV_RV32 core, the timer module in the MIV_ESS
+ can be configured as follows:
+ - Internal MTIME External MTIME IRQ
+ Generate the MTIME internally(MIV_RV32) and have a timer interrupt input
+ to the core as external pin(from MIV_ESS).
+
+ - External MTIME Internal MTIME IRQ
+ Generate the time value externally(from MIV_ESS), in this case a 64-bit
+ port will open in the MIV_RV32 core as input and MIV_ESS will output the
+ 64-bit TIME_COUNT value. The generation of mtimecmp and interrupt is
+ done internally(MIV_RV32).
+
+ - External MTIME External MTIME IRQ
+ Generate both the time and timer interrupt externally.
+ In this case 64-bit port will be available on the Mi-V RV32 core as input
+ and a 1 pin port will be available for timer interrupt.
+
+ The design must be configured accordingly to use these combinations in the
+ firmware.
+
+ No MIV_TIMER hardware configuration parameters are used by the driver, apart
+ from MIV_TIMER base address. Hence, no additional configuration files are
+ required to use the driver.
+
+ @section theory_op Theory of Operation
+
+ The MIV_TIMER module is a simple systick timer which can generate a timer
+ interrupt signal for the system at specific intervals specified by the
+ parameters that can be passed by the user.
+ These interrupt signal are then fed to the MIV_RV32 core via timer interrupt.
+
+ The operation of MIV_TIMER is divided into following steps:
+ - Initialization
+ - Configuration
+ - Read/Write TIME
+
+ ## Initialization
+ The MIV_TIMER is first initialized by a call to MIV_TIMER_init(). This
+ function initializes the instance of Mi-V TIMER with the base address.
+ The MIV_TIMER_init() function must be called before any other Mi-V Timer driver
+ function.
+
+ ## Configuration
+ The Mi-V TIMER configuration includes writing the mtimecmp register with the
+ initial time value at which timer interrupt should be generated.
+ When the mtime register value becomes greater than or equal to mtimecmp value,
+ a timer interrupt signal(TIMER_IRQ) is generated.
+
+ ## Read/Write TIME
+ The time value can be read by reading the mtime register via call to the
+ MIV_TIMER_read_mtime(). This function reads the MTIME register which contains
+ the 64-bit value of the timer count. The count increments by 1 every time the
+ prescale ticks. This function returns 64-bit MTIME_COUNT value which is the
+ current value of timer count.
+
+ The time value read in the MIV_TIMER_read_mtime() function can be written to
+ the mtimecmp register by calling MIV_TIMER_write_mtimecmp() to generate
+ periodic interrupts.
+ The writing of the mtimecmp register should be done in the systick_handler()
+ function.
+ */
+
+#ifndef MIV_TIMER_H_
+#define MIV_TIMER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+
+#else
+#include "hal.h"
+#endif
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_SUCCESS
+=====================
+
+The MIV_TIMER_SUCCESS constant indicates successful configuration of
+Mi-V Timer module.
+*/
+#define MIV_TIMER_SUCCESS 0u
+
+/*-------------------------------------------------------------------------*//**
+MIV_TIMER_ERROR
+=====================
+
+The MIV_TIMER_ERROR constant indicates that there is an error with
+configuring the Mi-V Timer module.
+*/
+#define MIV_TIMER_ERROR 1u
+
+/*-------------------------------------------------------------------------*//*
+MIV_TIMER_MASK_32BIT
+=====================
+
+32-bit mask constant used in calculation of 64-bit register value.
+*/
+#define MIV_TIMER_MASK_32BIT 0xFFFFFFFFu
+
+/*-------------------------------------------------------------------------*//*
+Mi-V Timer register offsets
+=====================
+The MTIMECMP is the 64-bit timer compare register, it pre-sets the threshold
+which needs to be reached by the timer count register.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIMECMP_L_REG_OFFSET
+ - MIV_TIMER_MTIMECMP_H_REG_OFFSET
+
+The MTIME is the 64-bit register that contains the 64-bit timer count. The
+count increments by 1 every time the prescaler ticks.
+This 64-bit register is accessed with 2 32-bit address offset, lower 32-bits
+and higher 32-bits.
+ - MIV_TIMER_MTIME_L_REG_OFFSET
+ - MIV_TIMER_MTIME_H_REG_OFFSET
+
+The PRESCALE register is used to determine the amount of clock cycles the
+selected clock needs to go through, for MTIME register to increment count.
+ - MIV_TIMER_PRESCALAR_REG_OFFSET
+*/
+
+/// @cond private
+#define MIV_TIMER_MTIMECMP_L_REG_OFFSET 0x4000u
+#define MIV_TIMER_MTIMECMP_H_REG_OFFSET 0x4004u
+
+#define MIV_TIMER_MTIME_L_REG_OFFSET 0xBFF8u
+#define MIV_TIMER_MTIME_H_REG_OFFSET 0xBFFCu
+
+#define MIV_TIMER_PRESCALAR_REG_OFFSET 0x5000u
+/// @endcond
+
+/*-------------------------------------------------------------------------*//**
+ This structure holds the base address of the Mi-V Timer module and instance
+ of the Mi-V Timer register structure.
+*/
+typedef struct miv_timer_instance
+{
+ addr_t base_addr;
+} miv_timer_instance_t;
+
+/** The MIV_TIMER_init() is used to initialize the Mi-V Timer module. This
+ function will assign the base addresses of the Mi-V Timer module.
+ User should call this function before calling any of the Mi-V Timer driver
+ APIs.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param base_address
+ Base address of the Mi-V Timer module.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_init
+(
+ miv_timer_instance_t* this_timer,
+ addr_t base_addr
+)
+{
+ this_timer->base_addr = base_addr;
+}
+
+/** MIV_TIMER_read_current_time() is used to read the mtimecmp register values.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @return
+ This function returns 64-bit mtimecmp register value.
+ */
+static inline uint64_t
+MIV_TIMER_read_current_time
+(
+ miv_timer_instance_t* this_timer
+)
+{
+ volatile uint64_t read_data = 0u;
+ volatile uint32_t mtime_hi = 0u;
+ volatile uint32_t mtime_lo = 0u;
+
+ /* when mtime lower word is 0xFFFFFFFF, there will be rollover and
+ * returned value could be wrong. */
+ do {
+ mtime_hi = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H);
+ mtime_lo = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_L);
+
+ } while(mtime_hi != HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIME_H));
+
+ read_data = mtime_hi;
+
+ return(((read_data) << 32u) | mtime_lo);
+}
+
+/** MIV_TIMER_write_compare_time() is used to write to the MTIMECMP register in
+ the event of interrupt. User must use this function in the interrupt handler
+ to de-assert the MIV_TIMER interrupt.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param write_value
+ Value to write into the mtimecmp register.
+
+ @return
+ This function does not return any value.
+ */
+static inline void
+MIV_TIMER_write_compare_time
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t compare_reg_value
+)
+{
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H, MIV_TIMER_MASK_32BIT);
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_L,
+ (compare_reg_value & MIV_TIMER_MASK_32BIT));
+
+ HAL_set_32bit_reg(this_timer->base_addr, MIV_TIMER_MTIMECMP_H,
+ ((compare_reg_value >> 32u) & MIV_TIMER_MASK_32BIT));
+}
+
+/** The MIV_TIMER_config() is used to configure the MIV_ESS Timer module. The
+ prescale value serves to divide the count of clock cycles for the timer and
+ provides control over what point in time, the timer interrupt gets
+ asserted.
+
+ @param this_timer
+ Timer structure which holds the base address for the Mi-V Timer hardware
+ instance.
+
+ @param ticks
+ Number of ticks after which interrupt will be generated.
+
+ @return
+ This function returns Mi-V Timer configuration status.
+ */
+static inline uint32_t
+MIV_TIMER_config
+(
+ miv_timer_instance_t* this_timer,
+ uint64_t ticks
+)
+{
+ uint32_t ret_val = MIV_TIMER_ERROR;
+ uint64_t mtime_val = 0u;
+ uint32_t prescalar = 0u;
+ uint64_t miv_timer_increment = 0U;
+
+ prescalar = HAL_get_32bit_reg(this_timer->base_addr, MIV_TIMER_PRESCALAR);
+
+ miv_timer_increment = (uint64_t)(ticks) / prescalar;
+
+ if (miv_timer_increment > 0U)
+ {
+ mtime_val = MIV_TIMER_read_current_time(this_timer);
+
+ MIV_TIMER_write_compare_time(this_timer ,(mtime_val + miv_timer_increment));
+
+ ret_val = MIV_TIMER_SUCCESS;
+ }
+
+ return ret_val;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_TIMER_H */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
new file mode 100644
index 0000000..cbd9652
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.c
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Mi-V uDMA Soft IP bare-metal driver. This module is delivered as part of
+ * Mi-V Extended Sub System(MIV_ESS)
+ */
+
+#include "miv_udma_regs.h"
+#include "miv_udma.h"
+
+/***************************************************************************//**
+ * MIV_uDMA_init()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+)
+{
+ /* Assign the Mi-V uDMA base address to the uDMA instance structure */
+ this_udma->base_address = base_addr;
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_config()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+)
+{
+ /* Source memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, SRC_START_ADDR, src_addr);
+
+ /* Destination memory start address */
+ HAL_set_32bit_reg(this_udma->base_address, DEST_START_ADDR, dest_addr);
+
+ /* Data transfer size */
+ HAL_set_32bit_reg(this_udma->base_address, BLK_SIZE, transfer_size);
+
+ /* Configure the uDMA IRQ */
+ HAL_set_32bit_reg(this_udma->base_address, IRQ_CFG, irq_config);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_start()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Start the uDMA transfer */
+ HAL_set_32bit_reg(this_udma->base_address, CONTROL_SR, CTRL_START_TX_MASK);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_reset()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ /* Toggle the uDMA_reset bit to reset the uDMA.
+ * Resetting the uDMA will clear all the configuration made by
+ * MIV_uDMA_config().
+ *
+ * This function should be called from the interrupt handler to clear the
+ * IRQ.
+ */
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x1u);
+ HAL_set_32bit_reg_field(this_udma->base_address, CTRL_RESET_TX, 0x0u);
+}
+
+/***************************************************************************//**
+ * MIV_uDMA_read_status()
+ * See "miv_udma.h" for details of how to use this function.
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_udma
+)
+{
+ uint32_t status = 0u;
+
+ /* Read the status of the uDMA transfer.
+ * The transfer status register can be Error or Busy depending on the
+ * current uDMA transfer.
+ */
+ status = HAL_get_32bit_reg(this_udma->base_address, TX_STATUS);
+
+ return status;
+}
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
new file mode 100644
index 0000000..efa8731
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma.h
@@ -0,0 +1,290 @@
+/*******************************************************************************
+ * Copyright 2022-2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * This file contains the application programming interface for the MI-V Soft IP
+ * uDMA module driver. This module is delivered as a part of Mi-V Extended
+ * Sub-System(MIV_ESS).
+ */
+
+/*=========================================================================*//**
+ @mainpage Mi-V uDMA Bare Metal Driver.
+ The Mi-V uDMA bare metal software driver.
+
+ @section intro_sec Introduction
+ The Mi-V uDMA driver provides a set of functions to control the Mi-V uDMA
+ module in the Mi-V Extended Subsystem (MIV_ESS) soft-IP. The Mi-V uDMA module
+ allows peripherals with AHB interfaces to transfer data independently of the
+ MIV_RV32 RISC-V processor.
+
+ Following are the major features provided by the Mi-V uDMA driver:
+ - Initialization and configuration
+ - Start and reset the transaction
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependency
+ The application software should initialize and configure the Mi-V uDMA through
+ calling the MIV_uDMA_init() and MIV_uDMA_config() functions for each Mi-V
+ uDMA instance in the design.
+
+ The uDMA can operate in two possible transfer configurations:
+
+ - AHBL Read -> AHBL Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over an AHBL (mirrored main/initiator) write interface.
+
+ - AHBL Read -> TAS Write:
+ In this configuration, the uDMA reads data from the source memory over an
+ AHBL (mirrored main/initiator) read interface and writes data to the
+ destination memory over the TAS (mirrored main/initiator) write interface.
+
+ Note: The AHBL Read -> TAS Write configuration is out of scope for this
+ driver.
+
+ @section theory_op Theory of Operation
+ The uDMA module in the Mi-V Extended Sub System (MIV_ESS) is a single-channel
+ uDMA module that allows peripherals to perform read-write operations between
+ source and destination memory. The Mi-V uDMA driver is used in
+ interrupt-driven mode and uses the Mi-V uDMA IRQ signal to drive the
+ interrupt service routine (ISR), which signifies a transfer has completed.
+ The status is checked in the ISR to ensure the transfer is completed
+ successfully.
+ The reset operation in the ISR resets the Mi-V uDMA controller. Once the Mi-V
+ uDMA transfer is complete, Mi-V uDMA retires. To initiate another
+ transaction, Mi-V uDMA needs to be configured again.
+
+ The operation of the Mi-V uDMA driver is divided into the following
+ categories:
+ - Initialization
+ - Configuration
+ - Start and reset the transfer
+
+ Initialization and configuration:
+ Mi-V uDMA is first initialized by calling MIV_uDMA_init() function. This
+ function initializes the instance of Mi-V uDMA with the base address. The
+ MIV_uDMA_init() function must be called before calling any other Mi-V uDMA
+ driver functions.
+
+ The Mi-V uDMA is configured by calling MIV_uDMA_config() function. This
+ function configures the source_addr and dest_addr registers of the Mi-V
+ uDMA with source and destination addresses for Mi-V uDMA transfers.
+ This function also configures the transfer size and interrupt preference for
+ successful transfers using Mi-V uDMA.
+
+ Start and reset the transfer:
+ Once the Mi-V uDMA is configured, initiate the transfers by calling the
+ MIV_uDMA_start() function. Once the Mi-V uDMA transfer is started, it cannot
+ be aborted, and the status of the transfer should be read from the ISR by
+ calling the MIV_uDMA_read_status() function.
+
+ Reset the Mi-V uDMA to the default state by calling the MIV_uDMA_reset()
+ function. After performing the reset operation, reconfigure the Mi-V uDMA to
+ perform transfers as MIV_uDMA_reset() resets the Mi-V uDMA controller.
+ */
+
+#ifndef MIV_uDMA_H_
+#define MIV_uDMA_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "hal/hal.h"
+#include "hal/cpu_types.h"
+
+#else
+#include "hal.h"
+#include "cpu_types.h"
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_CTRL_IRQ_CONFIG
+ =====================
+
+ The MIV_uDMA_CTRL_IRQ_CONFIG macro is used to assert the uDMA IRQ when an error
+ occurs during a uDMA transfer or on the completion of a uDMA transfer.
+ */
+#define MIV_uDMA_CTRL_IRQ_CONFIG 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_BUSY
+ =====================
+
+ The MIV_uDMA_STATUS_BUSY macro is used to indicate that the uDMA transfer is
+ in progress.
+ */
+#define MIV_uDMA_STATUS_BUSY 1u
+
+/*-------------------------------------------------------------------------*//**
+ MIV_uDMA_STATUS_ERROR
+ =====================
+
+ The MIV_uDMA_STATUS_ERROR macro is used to indicate that the last uDMA
+ transfer has caused an error.
+ */
+#define MIV_uDMA_STATUS_ERROR 2u
+
+/***************************************************************************//**
+ * This structure holds the base of the Mi-V uDMA module, which is used in the
+ * other functions of the driver to access the uDMA registers.
+ */
+typedef struct miv_udma_instance
+{
+ addr_t base_address;
+} miv_udma_instance_t;
+
+/***************************************************************************//**
+ * The MIV_uDMA_init() function assigns the base address of the Mi-V uDMA module
+ * to the uDMA instance structure.
+ * This address is used in a later part of the driver to access the uDMA
+ * registers.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return a value.
+ */
+void
+MIV_uDMA_init
+(
+ miv_udma_instance_t* this_udma,
+ addr_t base_addr
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_config() function is used to configure the Mi-V uDMA controller.
+ * This function will set the source address, destination address, block size,
+ * and IRQ configuration register.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @param base_addr
+ * Base address of the Mi-V uDMA.
+ *
+ * @param src_addr
+ * Source address of memory from where the uDMA reads the data.
+ *
+ * @param dest_addr
+ * Destination address where the data is written from src_addr.
+ *
+ * @param transfer_size
+ * Number of 32-bit words to transfer.
+ *
+ * @param irq_config
+ * uDMA IRQ configuration
+ * - When set, the IRQ is asserted when an error occurs during a uDMA
+ * transfer or on the completion of the uDMA transfer.
+ * - When clear, the IRQ is only asserted when an error occurs during a
+ * uDMA transfer.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_config
+(
+ miv_udma_instance_t* this_udma,
+ addr_t src_addr,
+ addr_t dest_addr,
+ uint32_t transfer_size,
+ uint32_t irq_config
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_start() function is used to start the uDMA transfer.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_start
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_reset() function is used to clear the uDMA interrupt and reset
+ * the uDMA transfer.
+ *
+ * This function should be called from the interrupt handler to reset the values
+ * set during MIV_uDMA_config().
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * This function does not return any value.
+ */
+void
+MIV_uDMA_reset
+(
+ miv_udma_instance_t* this_udma
+);
+
+/***************************************************************************//**
+ * The MIV_uDMA_read_status() function is used to read the status of the uDMA
+ * transfer. When interrupt is enabled, this function can be called from the
+ * interrupt handler to know the reason for a uDMA interrupt.
+ *
+ * @param this_udma
+ * This parameter is a pointer to the miv_udma_instance_t structure, which
+ * holds the base address of the Mi-V uDMA module.
+ *
+ * @return
+ * The return value indicates an error due to the busy status of the uDMA
+ * channel.
+ *
+ * |Bit Number| Name | Description |
+ * |----------|---------|------------------------------------------------------|
+ * | 0 | Busy | When set indicates that uDMA transfer is in progress|
+ * | 1 | Error | When set indicates that last uDMA transfer caused an|
+ * | | | error. |
+ */
+uint32_t
+MIV_uDMA_read_status
+(
+ miv_udma_instance_t* this_pdma
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_uDMA_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
new file mode 100644
index 0000000..14d0759
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_udma/miv_udma_regs.h
@@ -0,0 +1,94 @@
+ /*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file contains Register bit offsets and masks definitions for MI-V Soft
+ * IP uDMA module driver. This module is delivered as a part of Mi-V
+ * extended Sub-System(ESS) MIV_ESS.
+ */
+
+#ifndef MIV_UDMA_APB_REGISTERS
+#define MIV_UDMA_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**************************************************************************//**
+ * Control start/Reset register details
+ */
+
+#define CONTROL_SR_REG_OFFSET 0x0u
+
+/* Control start/Reset register bits */
+#define CONTROL_SR_OFFSET 0x00u
+#define CONTROL_SR_MASK 0x03u
+#define CONTROL_SR_SHIFT 0u
+
+/* uDMA Control Start Transfer */
+
+#define CTRL_START_TX_OFFSET 0x00u
+#define CTRL_START_TX_MASK 0x01u
+#define CTRL_START_TX_SHIFT 0u
+
+/* uDMA Control Reset Transfer */
+#define CTRL_RESET_TX_OFFSET 0x00u
+#define CTRL_RESET_TX_MASK 0x02u
+#define CTRL_RESET_TX_SHIFT 1u
+
+/**************************************************************************//**
+ * IRQ Configuration register details
+ */
+#define IRQ_CFG_REG_OFFSET 0x4u
+
+/* Control start/Reset register bits */
+#define IRQ_CFG_OFFSET 0x04u
+#define IRQ_CFG_MASK 0x01u
+#define IRQ_CFG_SHIFT 0u
+
+/***************************************************************************//**
+ * Transfer Status register details
+ */
+#define TX_STATUS_REG_OFFSET 0x08u
+
+/* Transfer status register bits */
+#define TX_STATUS_OFFSET 0x08u
+#define TX_STATUS_MASK 0x03u
+#define TX_STATUS_SHIFT 0u
+
+/***************************************************************************//**
+ * Source Memory Start Address Register
+ */
+#define SRC_START_ADDR_REG_OFFSET 0x0cu
+
+/* Source Memory Start Address Register bits */
+#define SRC_START_ADDR_OFFSET 0x0cu
+#define SRC_START_ADDR_MASK 0xFFFFFFFFu
+#define SRC_START_ADDR_SHIFT 0u
+
+/***************************************************************************//**
+ * Destination Memory Start Address register details
+ */
+#define DEST_START_ADDR_REG_OFFSET 0x10u
+
+/* Destination Memory Start Address register bits */
+#define DEST_START_ADDR_OFFSET 0x10u
+#define DEST_START_ADDR_MASK 0xFFFFFFFFu
+#define DEST_START_ADDR_SHIFT 0x0u
+
+/***************************************************************************//**
+ * Block Size register details
+ */
+#define BLK_SIZE_REG_OFFSET 0x14u
+
+/* Destination Memory Start Address register bits */
+#define BLK_SIZE_OFFSET 0x14u
+#define BLK_SIZE_MASK 0xFFFFFFFFu
+#define BLK_SIZE_SHIFT 0x0u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_UDMA_APB_REGISTERS */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
new file mode 100644
index 0000000..525928a
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.c
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog.h
new file mode 100644
index 0000000..8877e55
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/fpga_ip/miv_watchdog/miv_watchdog_regs.h
new file mode 100644
index 0000000..2fca983
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/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/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.c b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.c
new file mode 100644
index 0000000..a040ce4
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.c
@@ -0,0 +1,438 @@
+/**************************************************************************//**
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This file implements access functions for the PAC1934 using the MSS I2C
+ * driver APIs
+ *
+ */
+#include
+#if 0
+#include "drivers/mss/mss_mmuart/mss_uart.h"
+#include "mpfs_hal/mss_hal.h"
+#include "pac1934_regs.h"
+#include "drivers/mss/mss_i2c/mss_i2c.h"
+
+
+static mss_uart_instance_t * const gp_usr_uart = &g_mss_uart0_lo;
+unsigned long VPowerACC[4] = {0},VBus[4] = {0}, VSense[4] = {0}, \
+ VBusAvg[4] = {0}, VSenseAvg[4] = {0}, VPower[4] = {0};
+
+static mss_i2c_status_t do_write_transaction
+(
+ uint8_t serial_addr,
+ uint8_t * tx_buffer,
+ uint8_t write_length
+);
+
+/*------------------------------------------------------------------------------
+ * MSS I2C instance
+ */
+#define I2C_MASTER &g_mss_i2c1_lo
+#define I2C_SLAVE &g_mss_i2c0_lo
+
+/*------------------------------------------------------------------------------
+ * I2C master serial address.
+ */
+#define MASTER_SER_ADDR 0x21
+
+/*-----------------------------------------------------------------------------
+ * I2C slave serial address.
+ */
+#define SLAVE_SER_ADDR 0x20
+#define CURREN_SNSOR_ADDR 0x10
+
+#define BUFFER_SIZE 32u
+static uint8_t g_master_rx_buf[BUFFER_SIZE];
+static uint8_t g_master_tx_buf[BUFFER_SIZE];
+static uint8_t g_slave_rx_buffer[BUFFER_SIZE];
+static uint8_t g_slave_tx_buffer[BUFFER_SIZE];
+
+/*-----------------------------------------------------------------------------
+ * I2C operation timeout value in mS. Define as MSS_I2C_NO_TIMEOUT to disable
+ * the timeout functionality.
+ */
+#define DEMO_I2C_TIMEOUT 3000u
+
+/*-----------------------------------------------------------------------------
+ * UI Buffer
+ */
+#define UIBufSize 100
+#define lineSymbol "+"
+uint8_t g_ui_buf[UIBufSize] = {0};
+
+/* Draw UI */
+#define windowWidth UIBufSize
+#define windowHeight UIBufSize
+
+/*------------------------------------------------------------------------------
+ I2C-0 completion handler
+ */
+static void i2c0_completion_handler(mss_i2c_instance_t * instance, mss_i2c_status_t status)
+{
+ if(status == MSS_I2C_SUCCESS)
+ {
+ }
+ else
+ {
+ ASSERT(0);
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * Perform write-read transaction with parameters gathered from the command
+ * line interface.
+ */
+static mss_i2c_status_t do_write_read_transaction
+(
+ uint8_t serial_addr,
+ uint8_t * tx_buffer,
+ uint8_t write_length,
+ uint8_t * rx_buffer,
+ uint8_t read_length
+)
+{
+ mss_i2c_status_t status;
+
+ MSS_I2C_write_read(I2C_MASTER,
+ serial_addr,
+ tx_buffer,
+ write_length,
+ rx_buffer,
+ read_length,
+ MSS_I2C_RELEASE_BUS);
+
+ status = MSS_I2C_wait_complete(I2C_MASTER, MSS_I2C_NO_TIMEOUT);
+
+ return status;
+}
+
+/* Check PAC1934 sensor register value */
+static unsigned long sensor_reg_check(uint32_t reg)
+{
+ long value = 0;
+ mss_i2c_status_t instance;
+ uint8_t num_receive_bytes = 0;
+ float voltage = 0;
+
+ g_master_tx_buf[0] = reg;
+
+ if((reg == 0x00u) | (reg == 0x1Eu) | (reg == 0x1Fu)) /* refresh */
+ {
+ instance = do_write_transaction(CURREN_SNSOR_ADDR, g_master_tx_buf, 1u);
+ for(uint32_t cnt=0u; cnt < 7250000u; cnt++); /* min 2ms TODO: improve this*/
+ }
+ else if ((reg >= 0x3u) && (reg <= 0x6u)) /* Vpower_acc */
+ {
+ num_receive_bytes = 6u;
+ instance = do_write_read_transaction(CURREN_SNSOR_ADDR,
+ g_master_tx_buf,
+ 0x01u,
+ g_master_rx_buf,
+ num_receive_bytes);
+ }
+ else if ((reg >= 0x7u) && (reg <= 0x16u)) /* vbus, Vsense, Vsense_avg*/
+ {
+ num_receive_bytes = 2u;
+ instance = do_write_read_transaction(CURREN_SNSOR_ADDR,
+ g_master_tx_buf,
+ 0x01U,
+ g_master_rx_buf,
+ num_receive_bytes);
+ }
+ else if ((reg >= 0x17u) && (reg <= 0x1Au)) /* Vpower */
+ {
+ num_receive_bytes = 4u;
+ instance = do_write_read_transaction(CURREN_SNSOR_ADDR,
+ g_master_tx_buf,
+ 0x01U,
+ g_master_rx_buf,
+ num_receive_bytes);
+ }
+ else if ((reg >= 0xFD) && (reg <= 0xFF)) /* IDs */
+ {
+ num_receive_bytes = 1u;
+ instance = do_write_read_transaction(CURREN_SNSOR_ADDR,
+ g_master_tx_buf,
+ 0x01U,
+ g_master_rx_buf,
+ num_receive_bytes);
+ }
+ else
+ {
+ ASSERT(0U);
+ }
+
+ if(MSS_I2C_SUCCESS == instance)
+ {
+ if ((reg >= 0x3) && (reg <= 0x6)) /*Vpower_acc*/
+ {
+ value = g_master_rx_buf[0];
+ value = value << 8;
+ value = value + g_master_rx_buf[1];
+ value = value << 8;
+ value = value + g_master_rx_buf[2];
+ value = value << 8;
+ value = value + g_master_rx_buf[3];
+ value = value << 8;
+ value = value + g_master_rx_buf[4];
+ value = value << 8;
+ value = value + g_master_rx_buf[5];
+ }
+ else if ((reg >= 0x7) && (reg <= 0x16)) /* vbus, Vsense, Vsense_avg */
+ {
+ value = g_master_rx_buf[0];
+ value = value << 8;
+ value = value + g_master_rx_buf[1];
+ }
+ else if ((reg >= 0x17) && (reg <= 0x1A)) /* Vpower */
+ {
+ value = g_master_rx_buf[0];
+ value = value << 8;
+ value = value + g_master_rx_buf[1];
+ value = value << 8;
+ value = value + g_master_rx_buf[2];
+ value = value << 8;
+ value = value + g_master_rx_buf[3];
+ }
+ else if ((reg >= 0xFD) && (reg <= 0xFF)) /* IDs */
+ {
+ value = g_master_rx_buf[0];
+ }
+
+ return(value);
+ }
+ else
+ {
+ return (0xFFFFFFFFUL);
+ }
+}
+
+void cls(void)
+{
+ for (uint16_t x = 0u; x < windowHeight; x++)
+ {
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ }
+}
+
+void drawBar(void)
+{
+ /* Draw bar */
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+
+}
+
+void blankLine(void)
+{
+ /* Draw name */
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"+ +");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+
+}
+
+void drawName(void)
+{
+ /* Draw name */
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)" ---------------------------------- ");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"+++++++++++++++| Reading Current sensor over I2C |++++++++++++++");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)" ---------------------------------- ");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+}
+
+void PAC1934_drawISense(void)
+{
+ volatile float isense0,isense1,isense2,isense3;
+
+ for (uint16_t cnt = 0u; cnt < UIBufSize; cnt++)
+ {
+ g_ui_buf[cnt] = 0u;
+ }
+
+ sensor_reg_check(REFRESH_REG);
+ VBus[0] = sensor_reg_check(VSENSE1_AVG_REG);
+ isense0 = (VBus[0u]*10000.0)/65535.0;
+
+ VBus[1] = sensor_reg_check(VSENSE2_AVG_REG);
+ isense1 = (VBus[1u]*10000.0)/65535.0;
+
+ VBus[2] = sensor_reg_check(VSENSE3_AVG_REG);
+ isense2 = (VBus[2u]*10000.0)/65535.0;
+
+ VBus[3] = sensor_reg_check(VSENSE4_AVG_REG);
+ isense3 = (VBus[3u]*10000.0)/65535.0;
+
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\rCurrent values");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)" IVDD_REG IVDDA25 IVDD25 IVDDA_REG ");
+ MSS_UART_polled_tx(gp_usr_uart, g_ui_buf, UIBufSize);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ sprintf((char*)&g_ui_buf, " %08.3fma %08.3fma %08.3fma %08.3fma ",
+ (VBus[0u]*10000.0)/65535.0,
+ (VBus[1u]*10000.0)/65535.0,
+ (VBus[2u]*10000.0)/65535.0,
+ (VBus[3u]*10000.0)/65535.0);
+ MSS_UART_polled_tx(gp_usr_uart, g_ui_buf, UIBufSize);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r\n\r\n\r\n\r");
+}
+
+void PAC1934_drawVB(void)
+{
+ for (uint16_t cnt = 0u; cnt < UIBufSize; cnt++)
+ {
+ g_ui_buf[cnt] = 0u;
+ }
+ sensor_reg_check(REFRESH_REG);
+ VBus[0u] = sensor_reg_check(VBUS1_AVG_REG);
+ VBus[1u] = sensor_reg_check(VBUS2_AVG_REG);
+ VBus[2u] = sensor_reg_check(VBUS3_AVG_REG);
+ VBus[3u] = sensor_reg_check(VBUS4_AVG_REG);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r\n\rVoltage values");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)" VDD_REG VDDA25 VDD25 VDDA_REG ");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ sprintf((char*)&g_ui_buf, " %04.2fv %04.2fv %04.2fv %04.2fv ",
+ VBus[0]*32.0/65535.0,
+ VBus[1]*32.0/65535.0,
+ VBus[2]*32.0/65535.0,
+ VBus[3]*32.0/65535.0);
+ MSS_UART_polled_tx(gp_usr_uart, g_ui_buf, UIBufSize);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+}
+
+void drawVPowerAcc(uint32_t *VPower)
+{
+ /* Draw name */
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)" VPowerACC1 VPowerACC2 VPowerACC3 VPowerACC4 ");
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)lineSymbol);
+ MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t *)"\n\r");
+}
+
+/**************************************************************************//**
+ * MSS I2C accessing current sensor PAC1934
+ */
+int32_t PAC1934_sensor_probe(void)
+{
+ uint8_t cmd_idx = 0;
+ int32_t i2c_test_result = -1;
+
+ PLIC_init();
+ PLIC_SetPriority(I2C0_MAIN_PLIC, 2);
+ PLIC_SetPriority(I2C1_MAIN_PLIC, 2);
+ PLIC_SetPriority(I2C1_ALERT_PLIC, 2);
+ PLIC_SetPriority(I2C1_SUS_PLIC, 2);
+
+ __enable_irq();
+
+ PLIC_EnableIRQ(I2C0_MAIN_PLIC);
+ PLIC_EnableIRQ(I2C1_MAIN_PLIC);
+ PLIC_EnableIRQ(I2C1_ALERT_PLIC);
+ PLIC_EnableIRQ(I2C1_SUS_PLIC);
+
+ /*-------------------------------------------------------------------------
+ * Initialize the MSS I2C master Driver
+ */
+ MSS_I2C_init(I2C_MASTER, MASTER_SER_ADDR, MSS_I2C_PCLK_DIV_192);
+ MSS_I2C_register_transfer_completion_handler(I2C_MASTER, i2c0_completion_handler);
+
+
+ VPowerACC[0] = sensor_reg_check(PID_REG);
+ VPowerACC[1] = sensor_reg_check(MID_REG);
+ VPowerACC[2] = sensor_reg_check(REV_REG);
+
+ if ((0x5b == VPowerACC[0]) && (0x5d == VPowerACC[1]) && (0x03 == VPowerACC[2]))
+ {
+ i2c_test_result= 0u;
+ }
+ else
+ {
+ i2c_test_result= -1;
+ }
+
+ return(i2c_test_result);
+}
+
+mss_i2c_slave_handler_ret_t slave_write_handler
+(
+ mss_i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+)
+{
+ uint8_t loop_count;
+
+ if (rx_size > BUFFER_SIZE) /* Safety check and limit the data length */
+ {
+ rx_size = BUFFER_SIZE;
+ }
+
+ /* Copy only the data we have received */
+ for (loop_count = 0; loop_count < rx_size; loop_count++)
+ {
+ g_slave_tx_buffer[loop_count] = g_slave_rx_buffer[loop_count];
+ }
+
+ return MSS_I2C_REENABLE_SLAVE_RX;
+}
+
+/*------------------------------------------------------------------------------
+ I2C-1 completion handler
+ */
+void i2c1_completion_handler(mss_i2c_instance_t * instance, mss_i2c_status_t status)
+{
+ if(status == MSS_I2C_SUCCESS)
+ {
+ //MSS_UART_polled_tx_string(gp_usr_uart, (const uint8_t*)"\rI2C1 Transfer completed.\n\r");
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * Perform write transaction with parameters gathered from the command line
+ * interface. This function is called as a result of the user's input in the
+ * command line interface.
+ */
+static mss_i2c_status_t do_write_transaction
+(
+ uint8_t serial_addr,
+ uint8_t * tx_buffer,
+ uint8_t write_length
+)
+{
+ mss_i2c_status_t status;
+
+ MSS_I2C_write(I2C_MASTER, serial_addr, tx_buffer, write_length,
+ MSS_I2C_RELEASE_BUS);
+
+ status = MSS_I2C_wait_complete(I2C_MASTER, DEMO_I2C_TIMEOUT);
+
+ return status;
+}
+
+/*------------------------------------------------------------------------------
+ * Service the I2C timeout functionality (SysTick_Handler is called every 10mS).
+ */
+void SysTick_Handler_h0_IRQHandler(void)
+{
+ MSS_I2C_system_tick(I2C_MASTER, 10);
+ MSS_I2C_system_tick(I2C_SLAVE, 10);
+}
+
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.h
new file mode 100644
index 0000000..f7fd450
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934.h
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * Copyright 2019-2020 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.
+ *
+ * PolarFire SoC Microprocessor Subsystem I2C bare metal software driver
+ * public API.
+ *
+ */
+
+#ifndef PAC1934_H_
+#define PAC1934_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+
+/**
+ * typedefs
+ */
+
+
+/**
+ * extern variables
+ */
+
+/**
+ * functions
+ */
+
+void PAC1934_drawVB(void);
+void PAC1934_drawISense(void);
+int32_t PAC1934_sensor_probe(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAC1934_H_ */
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934_regs.h
new file mode 100644
index 0000000..61629a8
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/drivers/off-chip/pac1934/pac1934_regs.h
@@ -0,0 +1,55 @@
+/**************************************************************************//**
+ * Copyright 2019-2021 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Register defines for PAC1934
+ *
+ */
+
+#ifndef SRC_APPLICATION_HART0_PAC1934_REGS_H_
+#define SRC_APPLICATION_HART0_PAC1934_REGS_H_
+
+#define REFRESH_REG 0x00
+#define CTRL_REG 0x1
+#define ACC_COUNT_REG 0x2
+#define VPOWER1_ACC_REG 0x3
+#define VPOWER2_ACC_REG 0x4
+#define VPOWER3_ACC_REG 0x5
+#define VPOWER4_ACC_REG 0x6
+#define VBUS1_REG 0x7
+#define VBUS2_REG 0x8
+#define VBUS3_REG 0x9
+#define VBUS4_REG 0xA
+#define VSENSE1_REG 0xB
+#define VSENSE2_REG 0xC
+#define VSENSE3_REG 0xD
+#define VSENSE4_REG 0xE
+#define VBUS1_AVG_REG 0xF
+#define VBUS2_AVG_REG 0x10
+#define VBUS3_AVG_REG 0x11
+#define VBUS4_AVG_REG 0x12
+#define VSENSE1_AVG_REG 0x13
+#define VSENSE2_AVG_REG 0x14
+#define VSENSE3_AVG_REG 0x15
+#define VSENSE4_AVG_REG 0x16
+#define VPOWER1_REG 0x17
+#define VPOWER2_REG 0x18
+#define VPOWER3_REG 0x19
+#define VPOWER4_REG 0x1A
+#define CHANNEL_DIS_REG 0x1C
+#define NEG_PWR_REG 0x1D
+#define REFRESH_G_REG 0x1E
+#define REFRESH_V_REG 0x1F
+#define SLOW_REG 0x20
+#define CTRL_ACT_REG 0x21
+#define CHANNEL_DIS_ACT_REG 0x22
+#define NEG_PWR_ACT_REG 0x23
+#define CTRL_LAT_REG 0x24
+#define CHANNEL_DIS_LAT_REG 0x25
+#define NEG_PWR_LAT_REG 0x26
+#define PID_REG 0xFD
+#define MID_REG 0xFE
+#define REV_REG 0xFF
+
+#endif /* SRC_APPLICATION_HART0_PAC1934_REGS_H_ */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/hal/cpu_types.h b/user-crypto/miv-rv32-message-authentication/src/platform/hal/cpu_types.h
new file mode 100644
index 0000000..ef8ab20
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal.h b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal.h
new file mode 100644
index 0000000..7eec17a
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_assert.h b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_assert.h
new file mode 100644
index 0000000..1e18b54
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_assert.h
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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
+
+#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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_irq.c b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_irq.c
new file mode 100644
index 0000000..95a0775
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hal_irq.c
@@ -0,0 +1,45 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_macros.h b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_macros.h
new file mode 100644
index 0000000..189609c
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_macros.h
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.S b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.S
new file mode 100644
index 0000000..dd29223
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.S
@@ -0,0 +1,215 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.h b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.h
new file mode 100644
index 0000000..1a24309
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/hal/hw_reg_access.h
@@ -0,0 +1,239 @@
+/***************************************************************************//**
+ * Copyright 2019-2022 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
new file mode 100644
index 0000000..474eb43
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-execute-in-place.ld
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-ram.ld b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-ram.ld
new file mode 100644
index 0000000..53076a0
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv-rv32-ram.ld
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright 2019 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 = 1k; /* 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_assert.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_assert.h
new file mode 100644
index 0000000..b3912ed
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_assert.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2022 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * MIV_RV32 HAL Embedded Software
+ *
+ */
+#ifndef MIV_RV32_ASSERT_HEADER
+#define MIV_RV32_ASSERT_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * ASSERT() implementation.
+ ******************************************************************************/
+/* Disable assertions if we do not recognize the compiler. */
+#if defined ( __GNUC__ )
+#if defined(NDEBUG)
+#define ASSERT(CHECK)
+#else
+#define ASSERT(CHECK)\
+ do { \
+ if (!(CHECK)) \
+ { \
+ __asm__ volatile ("ebreak"); \
+ }\
+ } while(0);
+
+#endif /* NDEBUG check */
+#endif /* compiler check */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MIV_RV32_ASSERT_HEADER */
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_entry.S b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_entry.S
new file mode 100644
index 0000000..0ea3172
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_entry.S
@@ -0,0 +1,590 @@
+/*******************************************************************************
+ * Copyright 2019 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
+
+#define MTIMEH_ADDR 0x200BFFCu
+
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+#if defined(MIV_FP_CONTEXT_SAVE) && defined(__riscv_flen)
+#define SP_SHIFT_OFFSET 64
+#else
+#define SP_SHIFT_OFFSET 32
+#endif
+
+.macro STORE_CONTEXT
+ addi sp, sp, -SP_SHIFT_OFFSET*REGBYTES
+ SREG x1, 0 * REGBYTES(sp)
+ 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 __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ fsw f0, 31*REGBYTES(sp)
+ fsw f1, 32*REGBYTES(sp)
+ fsw f2, 33*REGBYTES(sp)
+ fsw f3, 34*REGBYTES(sp)
+ fsw f4, 35*REGBYTES(sp)
+ fsw f5, 36*REGBYTES(sp)
+ fsw f6, 37*REGBYTES(sp)
+ fsw f7, 38*REGBYTES(sp)
+ fsw f8, 39*REGBYTES(sp)
+ fsw f9, 40*REGBYTES(sp)
+ fsw f10, 41*REGBYTES(sp)
+ fsw f11, 42*REGBYTES(sp)
+ fsw f12, 43*REGBYTES(sp)
+ fsw f13, 44*REGBYTES(sp)
+ fsw f14, 45*REGBYTES(sp)
+ fsw f15, 46*REGBYTES(sp)
+ fsw f16, 47*REGBYTES(sp)
+ fsw f17, 48*REGBYTES(sp)
+ fsw f18, 49*REGBYTES(sp)
+ fsw f19, 50*REGBYTES(sp)
+ fsw f20, 51*REGBYTES(sp)
+ fsw f21, 52*REGBYTES(sp)
+ fsw f22, 53*REGBYTES(sp)
+ fsw f23, 54*REGBYTES(sp)
+ fsw f24, 55*REGBYTES(sp)
+ fsw f25, 56*REGBYTES(sp)
+ fsw f26, 57*REGBYTES(sp)
+ fsw f27, 58*REGBYTES(sp)
+ fsw f28, 59*REGBYTES(sp)
+ fsw f29, 60*REGBYTES(sp)
+ fsw f30, 61*REGBYTES(sp)
+ fsw f31, 62*REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+.endm
+
+ .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
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE22_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_SUBSYSR_IRQHandler
+#endif /*MIV_RV32_V3_0*/
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE23_trap_entry:
+ j vector_SUBSYS_IRQHandler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /*MIV_RV32_V3_0*/
+
+MSYS_MIE24_trap_entry:
+ j vector_MSYS_EI0_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE25_trap_entry:
+ j vector_MSYS_EI1_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE26_trap_entry:
+ j vector_MSYS_EI2_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE27_trap_entry:
+ j vector_MSYS_EI3_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE28_trap_entry:
+ j vector_MSYS_EI4_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE29_trap_entry:
+ j vector_MSYS_EI5_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+MSYS_MIE30_trap_entry:
+#ifndef MIV_RV32_V3_0
+ j vector_MSYS_EI6_trap_handler
+#else
+ j vector_SUBSYS_IRQHandler
+#endif
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+
+#ifndef MIV_RV32_V3_0
+MSYS_MIE31_trap_entry:
+ j vector_MSYS_EI7_trap_handler
+#ifdef __riscv_compressed
+ .2byte 0
+#endif
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+.align 4
+generic_trap_handler:
+ STORE_CONTEXT
+ csrr a0, mcause
+ csrr a1, mepc
+ jal handle_trap
+ j generic_restore
+
+vector_sw_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_soft_interrupt
+ j generic_restore
+
+vector_tmr_trap_handler:
+ STORE_CONTEXT
+ jal handle_m_timer_interrupt
+ j generic_restore
+
+vector_ext_trap_handler:
+ STORE_CONTEXT
+#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:
+ STORE_CONTEXT
+ jal MGEUI_IRQHandler
+ j generic_restore
+
+vector_MGECI_trap_handler:
+ STORE_CONTEXT
+ jal MGECI_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI0_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI0_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI1_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI1_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI2_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI2_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI3_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI3_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI4_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI4_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI5_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI5_IRQHandler
+ j generic_restore
+
+vector_SUBSYS_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYS_IRQHandler
+ j generic_restore
+
+#ifndef MIV_RV32_V3_0
+vector_MSYS_EI6_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI6_IRQHandler
+ j generic_restore
+
+vector_MSYS_EI7_trap_handler:
+ STORE_CONTEXT
+ jal MSYS_EI7_IRQHandler
+ j generic_restore
+
+
+vector_SUBSYSR_IRQHandler:
+ STORE_CONTEXT
+ jal SUBSYSR_IRQHandler
+ j generic_restore
+
+#endif /*MIV_RV32_V3_0*/
+#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)
+
+ #ifdef __riscv_flen
+ #ifdef MIV_FP_CONTEXT_SAVE
+ flw f0, 0 * REGBYTES(sp)
+ flw f1, 1 * REGBYTES(sp)
+ flw f2, 2 * REGBYTES(sp)
+ flw f3, 3 * REGBYTES(sp)
+ flw f4, 4 * REGBYTES(sp)
+ flw f5, 5 * REGBYTES(sp)
+ flw f6, 6 * REGBYTES(sp)
+ flw f7, 7 * REGBYTES(sp)
+ flw f8, 8 * REGBYTES(sp)
+ flw f9, 9 * REGBYTES(sp)
+ flw f10, 10 * REGBYTES(sp)
+ flw f11, 11 * REGBYTES(sp)
+ flw f12, 12 * REGBYTES(sp)
+ flw f13, 13 * REGBYTES(sp)
+ flw f14, 14 * REGBYTES(sp)
+ flw f15, 15 * REGBYTES(sp)
+ flw f16, 16 * REGBYTES(sp)
+ flw f17, 17 * REGBYTES(sp)
+ flw f18, 18 * REGBYTES(sp)
+ flw f19, 19 * REGBYTES(sp)
+ flw f20, 20 * REGBYTES(sp)
+ flw f21, 21 * REGBYTES(sp)
+ flw f22, 22 * REGBYTES(sp)
+ flw f23, 23 * REGBYTES(sp)
+ flw f24, 24 * REGBYTES(sp)
+ flw f25, 25 * REGBYTES(sp)
+ flw f26, 26 * REGBYTES(sp)
+ flw f27, 27 * REGBYTES(sp)
+ flw f28, 28 * REGBYTES(sp)
+ flw f29, 29 * REGBYTES(sp)
+ flw f30, 30 * REGBYTES(sp)
+ flw f31, 31 * REGBYTES(sp)
+ #endif /* __riscv_flen */
+ #endif /* MIV_FP_CONTEXT_SAVE */
+
+ addi sp, sp, SP_SHIFT_OFFSET*REGBYTES
+ mret
+
+ .section .text, "ax"
+handle_reset:
+/* Ensure instructions are not relaxed, since gp is not yet set */
+.option push
+.option norelax
+
+#ifndef MIV_RV32_V3_0
+ csrwi mstatus, 0
+ csrwi mie, 0
+ la ra, _start
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+ 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. */
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+
+ 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
+
+#else /* MIV_RV32_V3_0 */
+
+/* Clearnig this to be on safer side as RTL doesnt seem to clear it on reset. */
+#ifndef MIV_LEGACY_RV32
+ li t0, MTIMEH_ADDR
+ sw x0, 0(t0)
+#endif
+
+/* In the MIV_RV32 v3.1, the MTVEC exception base address is WARL, and can be
+ configured by the user at runtime */
+ 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
+#endif /*MIV_RV32_V3_0*/
+
+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 both MIV_RV32 v3.1 and v3.0 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.c b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.c
new file mode 100644
index 0000000..a112821
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.c
@@ -0,0 +1,410 @@
+/*******************************************************************************
+ * Copyright 2019 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.
+ */
+#ifndef MIV_RV32_EXT_TIMECMP
+#define WRITE_MTIMECMP(value) MTIMECMPH = MASK_32BIT; \
+ MTIMECMP = value & MASK_32BIT;\
+ MTIMECMPH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIMECMP(value)
+#endif
+
+#ifndef MIV_RV32_EXT_TIMER
+#define WRITE_MTIME(value) MTIME = value & MASK_32BIT;\
+ MTIMEH = (value >> 32u) & MASK_32BIT;
+#else
+#define WRITE_MTIME(value)
+#endif
+
+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 mrv_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 Reserved_IRQHandler(void);
+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 SUBSYS_IRQHandler(void);
+
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+extern void MSYS_EI6_IRQHandler(void);
+extern void MSYS_EI7_IRQHandler(void);
+extern void SUBSYSR_IRQHandler(void); // @suppress("Unused function declaration")
+#endif /*MIV_RV32_V3_0*/
+
+#endif /* MIV_LEGACY_RV32 */
+
+/*------------------------------------------------------------------------------
+ * 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;
+static uint64_t g_systick_cmp_value = 0U;
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t MRV_systick_config(uint64_t ticks)
+{
+ uint32_t ret_val = ERROR;
+ uint64_t remainder = ticks;
+ g_systick_increment = 0U;
+ g_systick_cmp_value = 0U;
+
+ while (remainder >= MTIME_PRESCALER)
+ {
+ remainder -= MTIME_PRESCALER;
+ g_systick_increment++;
+ }
+
+ g_systick_cmp_value = g_systick_increment + MRV_read_mtime();
+
+ if (g_systick_increment > 0U)
+ {
+ WRITE_MTIMECMP(g_systick_cmp_value);
+ 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)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ uint64_t mtime_at_irq = MRV_read_mtime();
+
+#ifndef NDEBUG
+ static volatile uint32_t d_tick = 0u;
+#endif
+
+ while(g_systick_cmp_value < (mtime_at_irq + MTIME_DELTA)) {
+ g_systick_cmp_value = g_systick_cmp_value + g_systick_increment;
+
+#ifndef NDEBUG
+ d_tick += 1;
+#endif
+ }
+/***************************************************************************//**
+ /*
+ * Note: If d_tick > 1 it means, that a system timer interrupt has been
+ * missed.
+ * Please ensure that interrupt handlers are as short as possible to prevent
+ * them stopping other interrupts from being handled. For example, if a
+ * system timer interrupt occurs during a software interrupt, the system
+ * timer interrupt will not be handled until the software interrupt handling
+ * is complete. If the software interrupt handling time is more than one
+ * systick interval, it will result in d_tick > 1.
+ * If you are running the program using the debugger and halt the CPU at a
+ * breakpoint, MTIME will continue to increment and interrupts will be
+ * missed; resulting in d_tick > 1.
+ */
+
+ WRITE_MTIMECMP(g_systick_cmp_value);
+
+ SysTick_Handler();
+
+ set_csr(mie, MIP_MTIP);
+}
+
+void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+ MRV_clear_soft_irq();
+}
+/*------------------------------------------------------------------------------
+ * 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 = mrv_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);
+ }
+ }
+}
+#else
+
+/*------------------------------------------------------------------------------
+ * MSYS local interrupts table
+ */
+void (* const local_irq_handler_table[16])(void) =
+{
+#ifndef MIV_RV32_V3_0
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ SUBSYS_IRQHandler,
+ SUBSYSR_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ MSYS_EI6_IRQHandler,
+ MSYS_EI7_IRQHandler
+#else
+ MGEUI_IRQHandler,
+ MGECI_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ Reserved_IRQHandler,
+ MSYS_EI0_IRQHandler,
+ MSYS_EI1_IRQHandler,
+ MSYS_EI2_IRQHandler,
+ MSYS_EI3_IRQHandler,
+ MSYS_EI4_IRQHandler,
+ MSYS_EI5_IRQHandler,
+ SUBSYS_IRQHandler,
+ Reserved_IRQHandler,
+#endif
+};
+
+/*------------------------------------------------------------------------------
+ * Jump to interrupt table containing local interrupts
+ */
+void handle_local_ei_interrupts(uint8_t irq_no)
+{
+ uint64_t mhart_id = read_csr(mhartid);
+ ASSERT(irq_no <= MIV_LOCAL_IRQ_MAX)
+ ASSERT(irq_no >= MIV_LOCAL_IRQ_MIN)
+
+ uint8_t ei_no = (uint8_t)(irq_no - MIV_LOCAL_IRQ_MIN);
+ (*local_irq_handler_table[ei_no])();
+}
+#endif /* MIV_LEGACY_RV32 */
+
+
+/*------------------------------------------------------------------------------
+ * Trap handler. This function is invoked in the non-vectored mode.
+ */
+void handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ uint64_t is_interrupt = mcause & MCAUSE_INT;
+
+ if (is_interrupt)
+ {
+#ifndef MIV_LEGACY_RV32
+ if (((mcause & MCAUSE_CAUSE) >= MIV_LOCAL_IRQ_MIN) && ((mcause & MCAUSE_CAUSE) <= MIV_LOCAL_IRQ_MAX))
+ {
+ handle_local_ei_interrupts((uint8_t)(mcause & MCAUSE_CAUSE));
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#else
+ if ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)
+#endif
+ {
+#ifndef MIV_LEGACY_RV32
+ External_IRQHandler();
+#else
+ handle_m_ext_interrupt();
+#endif
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT)
+ {
+ handle_m_soft_interrupt();
+ }
+ else if ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)
+ {
+ handle_m_timer_interrupt();
+ }
+ }
+ 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 /* NDEBUG */
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.h
new file mode 100644
index 0000000..9ce9ef6
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal.h
@@ -0,0 +1,773 @@
+/*******************************************************************************
+ * Copyright 2019 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+/*=========================================================================*//**
+ @mainpage MIV_RV32 Hardware Abstraction Layer
+
+ ==============================================================================
+ Introduction
+ ==============================================================================
+ This document describes the Hardware Abstraction Layer (HAL) for the MIV_RV32
+ Soft IP Core. This release of the HAL corresponds to the Soft IP core MIV_RV32
+ v3.1 release. It also supports earlier versions of the MIV_RV32 as well as the
+ legacy RV32 IP cores.
+ The preprocessor macros provided with the MIV_RV32 HAL are used to customize
+ it to target the Soft Processor IP version being used in your project.
+
+ The term "MIV_RV32" represents following two cores:
+ - MIV_RV32 v3.0 and later (the latest and greatest Mi-V soft processor)
+ - MIV_RV32IMC v2.1 (MIV_RV32 v3.0 is a drop in replacement for this core)
+ It is highly recommended to migrate your design to MIV_RV32 v3.1
+
+ The term, Legacy RV32 IP cores, represents following IP cores:
+ - MIV_RV32IMA_L1_AHB
+ - MIV_RV32IMA_L1_AXI
+ - MIV_RV32IMAF_L1_AHB
+
+ These legacy RV32 IP cores are deprecated. It is highly recommended to migrate
+ your designs to MIV_RV32 v3.1 (and subsequent IP releases) for the latest
+ enhancements, bug fixes, and support.
+
+ --------------------------------
+ MIV_RV32 V3.1
+ --------------------------------
+ This is the latest release of the MIV_RV32 Soft IP core. For more details,
+ refer to the MIV_RV32 User [Guide](https://www.microchip.com/en-us/products/fpgas-and-plds/ip-core-tools/miv-rv32)
+
+ The MIV_RV32 Core as well as this document use the terms defined below:
+
+ --------------------------------
+ - SUBSYS - Processor Subsystem for RISC-V
+ - OPSRV - Offload Processor Subsystem for RISC-V
+ - GPR - General Purpose Registers
+ - MGECIE - Machine GPR ECC Correctable Interrupt Enable
+ - MGEUIE - Machine GPR ECC Uncorrectable Interrupt Enable
+ - MTIE - Machine Timer Interrupt Enable
+ - MEIE - Machine External Interrupt Enable
+ - MSIE - Machine Software Interrupt Enable
+ - ISR - Interrupt Service Routine
+
+ ==============================================================================
+ Customizing MIV_RV32 HAL
+ ==============================================================================
+ To use the HAL with older releases of MIV_RV32, preprocessor macros have been
+ provided. Using these macros, any of the IP version is targeted.
+ The HAL is used to target any of the mentioned platforms by adding the
+ following macros in the way :
+ Project Properties > C/C++ Build > Settings > Preprocessor in Assembler and
+ Compiler settings.
+ The table below shows the macros corresponding to the MIV Core being used in
+ your libero project. By default, the HAL targets v3.1 of the IP core and no
+ macros need to be set for this configutation.
+
+ | Libero MI-V Soft IP Version | SoftConsole Macro |
+ |-----------------------------|-------------------|
+ | MIV_RV32 v3.1 | no macro required |
+ | MIV_RV32 v3.0 | MIV_CORE_V3_0 |
+ | Legacy RV32 Cores | MIV_LEGACY_RV32 |
+
+ --------------------------------
+ Interrupt Handling
+ --------------------------------
+ The MIE Register is defined as a enum in the HAL, and the table below is used
+ as a reference when the vectored interrupts are enabled in the GUI core
+ configurator.
+
+ The MIE register is a RISC-V Control and Status Register (CSR), which stands
+ for the Machine Interrupt Enable. This is used to enable the machine mode
+ interrupts in the MIV_RV32 hart. Refer to the RISC-V Priv spec for more details.
+
+ The following table shows the trap entry addresses when an interrupt occurs and
+ the vectored interrupts are enabled in the GUI configurator.
+
+ | MIE Register Bit | Interrupt Enable | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | MSYS_IE7 | mtvec.BASE + 0x7C |
+ | 30 | MSYS_IE6 | mtvec.BASE + 0x78 |
+ | 29 | MSYS_IE5 | mtvec.BASE + 0x74 |
+ | 28 | MSYS_IE4 | mtvec.BASE + 0x70 |
+ | 27 | MSYS_IE3 | mtvec.BASE + 0x6C |
+ | 26 | MSYS_IE2 | mtvec.BASE + 0x68 |
+ | 25 | MSYS_IE1 | mtvec.BASE + 0x64 |
+ | 24 | MSYS_IE0 | mtvec.BASE + 0x60 |
+ | 23 | SUBSYS_EI | mtvec.BASE + 0x5C |
+ | 22 | SUBSYSR | mtvec.BASE + 0x58 |
+ | 17 | MGECIE | mtvec.BASE + 0x44 |
+ | 16 | MGEUIE | mtvec.BASE + 0x40 |
+ | 11 | MEIE | mtvec.BASE + 0x2C |
+ | 7 | MTIE | mtvec.BASE + 0x1C |
+ | 3 | MSIE | mtvec.BASE + 0x0C |
+
+
+ For changes in MIE register map, see the [MIE Register Map for MIV_RV32 v3.0]
+ (#mie-register-map-for-miv_rv32-v3.0) section.
+
+ SUBSYSR is currently not being used by the core and is Reserved for future use.
+
+ The mtvec.BASE field corresponds to the bits [31:2], where mtvec stands for
+ Machine Trap Vector, and all traps set the PC to the the value stored in the
+ mtvec.BASE field when in Non-Vectored mode. In this case, a generic trap
+ handler is as an interrupt service routine.
+
+ When Vectored interrupts are enabled, use this formula to calculate the trap
+ address: (mtvec.BASE + 4*cause), where cause comes from the mcause CSR. The
+ mcause register is written with a code indicating the event that caused the trap.
+ For more details, see the RISC-V priv specification.
+
+ The MIV_RV32 Soft IP core does not contain a Platfrom Level Interrup Controller
+ (PLIC). It is advised to use the PLIC contained within the MIV_ESS sub-system.
+ Connect the PLIC interrupt output of the MIV_ESS to the EXT_IRQ pin on the
+ MIV_RV32.
+
+ The following table is the MIE register map for the MIV_RV32 Core V3.0. It only
+ highlights the differences between the V3.0 and V3.1 of the core.
+
+ --------------------------------
+ MIE Register Map for MIV_RV32 V3.0
+ --------------------------------
+
+ | MIE Register Bit | Target Interrupt | Vector Address |
+ |-------------------|------------------|----------------|
+ | 31 | Not in use | top table |
+ | 30 | SUBSYS_EI | addr + 0x78 |
+ | 23 | Not in use | Not in use |
+ | 22 | Not in use | Not in use |
+
+ Other interrupt bit postions like the MGEUIE and MSYS_IE5 to MSYS_IE0 remain
+ unchanged.
+
+ --------------------------------
+ Floating Point Interrupt Support
+ --------------------------------
+ When an interrupt is taken and Floating Point instructions are used in the
+ ISR, the floating point register context must be saved to resume the application
+ correctly. To use this feature, enable the provided macro in the
+ Softconsole build settings.
+ This feature is turned off by default as it adds overhead which is not required
+ when the ISR does not used FP insturctions and saving the general purpose
+ register context is sufficient.
+
+ | Macro Name | Definition |
+ |--------------------------|-------------------------------------------------|
+ | MIV_FP_CONTEXT_SAVE | Define to save the FP register file |
+
+
+ --------------------------------
+ SUBSYS - SubSystem for RISC-V
+ --------------------------------
+ SUBSYS stands for SubSystem for RISC-V. This was previously (MIV_RV32 v3.0)
+ known as OPSRV, which stands for "Offload Processor Subsystem
+ for RISC-V". See the earlier versions of the handbook for more details.
+ In the latest release of the MIV_RV32 IP core v3.1, OPSRV has been renamed to
+ SUBSYS. The MIV_RV32 HAL now uses SUBSYS instead of OPSRV.
+
+ *//*=========================================================================*/
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "miv_rv32_regs.h"
+#include "miv_rv32_plic.h"
+#include "miv_rv32_assert.h"
+#include "miv_rv32_subsys.h"
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "fpga_design_config/fpga_design_config.h"
+#else
+#include "hw_platform.h"
+#endif /*LEGACY_DIR_STRUCTURE*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Backwards Compatibility
+ =======================================
+ For application code using the older macro names and API functions, these macros
+ act as a compatibility layer and applications which use OPSRV API features work
+ due to these macro definitions. However, it is adviced to update your
+ application code to use the SUBSYS macros and API functions.
+
+ | Macro Name | Now Called |
+ |-------------------------|--------------------------|
+ | OPSRV_TCM_ECC_CE_IRQ | SUBSYS_TCM_ECC_CE_IRQ |
+ | OPSRV_TCM_ECC_UCE_IRQ | SUBSYS_TCM_ECC_UCE_IRQ |
+ | OPSRV_AXI_WR_RESP_IRQ | SUBSYS_AXI_WR_RESP_IRQ |
+ | MRV32_MSYS_OPSRV_IRQn | MRV32_SUBSYS_IRQn |
+ | MRV32_opsrv_enable_irq | MRV32_subsys_enable_irq |
+ | MRV32_opsrv_disable_irq | MRV32_subsys_disable_irq |
+ | MRV32_opsrv_clear_irq | MRV32_subsys_clear_irq |
+ | OPSRV_IRQHandler | SUBSYS_IRQHandler |
+ */
+
+/*-------------------------------------------------------------------------*//**
+ MTIME Timer Interrupt Constants
+ =======================================
+ These values contain the register addresses for the registers used by the
+ machine timer interrupt
+
+ MTIME_PRESCALER is not defined on the MIV_RV32IMC v2.0 and v2.1. By using this
+ definition the system crashes. For those core, use the following definition:
+
+ #define MTIME_PRESCALER 100u
+
+ MTIME and MTIMECMP
+ --------------------------------
+ MIV_RV32 core offers flexibility in terms of generating MTIME and MTIMECMP
+ registers internal to the core or using external time reference. There four
+ possible combinations:
+
+ - Internal MTIME and Internal MTIME IRQ enabled Generate the MTIME and MTIMECMP
+ registers internally. (The only combination available on legacy RV32 cores)
+
+ - Internal MTIME enabled and Internal MTIME IRQ disabled Generate the MTIME
+ internally and have a timer interrupt input to the core as external pin. In
+ this case, 1 pin port will be available on MIV_RV32 for timer interrupt.
+
+ - When the internal MTIME is disabled, and the Internal MTIME IRQ is enabled, the
+ system generates the time value externally and generates the mtimecmp and
+ interrupt internally (for example, a multiprocessor system with a shared time
+ between all cores). In this case, a 64-bit port is available on the MIV_RV32
+ core as input.
+
+ - Internal MTIME and Internal MTIME IRQ disabled Generate both the time and
+ timer interrupts externally. In this case a 64 bit port will be available on
+ the MIV_RV32 core as input, and a 1 pin port will be available for timer
+ interrupt.
+
+ To handle all these combinations in the firmware, the following constants must
+ be defined in accordance with the configuration that you have made on your
+ MIV_RV32 core design.
+
+ MIV_RV32_EXT_TIMER
+ --------------------------------
+ When defined, it means that the MTIME register is not available internal to
+ the core. In this case, a 64 bit port will be available on the MIV_RV32 core as
+ input. When this macro is not defined, it means that the MTIME register is
+ available internally to the core.
+
+ MIV_RV32_EXT_TIMECMP
+ --------------------------------
+ When defined, it means the MTIMECMP register is not available internally to
+ the core and the Timer interrupt input to the core comes as an external pin.
+ When this macro is not defined it means the that MTIMECMP register exists
+ internal to the core and that the timer interrupt is generated internally.
+
+NOTE: All these macros must not be defined if you are using a MIV_RV32 core.
+ */
+
+#define OPSRV_TCM_ECC_CE_IRQ SUBSYS_TCM_ECC_CE_IRQ
+#define OPSRV_TCM_ECC_UCE_IRQ SUBSYS_TCM_ECC_UCE_IRQ
+#define OPSRV_AXI_WR_RESP_IRQ SUBSYS_AXI_WR_RESP_IRQ
+#define MRV32_MSYS_OPSRV_IRQn MRV32_SUBSYS_IRQn
+#define MRV32_opsrv_enable_irq MRV32_subsys_enable_irq
+#define MRV32_opsrv_disable_irq MRV32_subsys_disable_irq
+#define MRV32_opsrv_clear_irq MRV32_subsys_clear_irq
+#define OPSRV_IRQHandler SUBSYS_IRQHandler
+
+/*-------------------------------------------------------------------------*//**
+ External IRQ
+ =======================================
+ Return value from External IRQ handler. This is used to disable the
+ External Interrupt.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | EXT_IRQ_KEEP_ENABLED | 0 | Keep external interrupts enabled |
+ | EXT_IRQ_DISABLE | 1 | Disable external interrupts |
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+#define MTIME_DELTA 5
+#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 /* MIV_LEGACY_RV32 */
+
+/* To maintain backward compatibility with FreeRTOS config code */
+#define PRCI_BASE 0x02000000UL
+
+#ifndef MIV_RV32_EXT_TIMECMP
+#define MTIMECMP (*(volatile uint32_t*)0x02004000UL)
+#define MTIMECMPH (*(volatile uint32_t*)0x02004004UL)
+#else
+#define MTIMECMP (0u)
+#define MTIMECMPH (0u)
+#endif
+
+#define MTIME_PRESCALER (*(volatile uint32_t*)0x02005000UL)
+
+#ifndef MIV_RV32_EXT_TIMER
+#define MTIME (*(volatile uint32_t*)0x0200BFF8UL)
+#define MTIMEH (*(volatile uint32_t*)0x0200BFFCUL)
+
+/***************************************************************************//**
+ MIMPID Register
+ The MIMPID register is a RISC-V Control and Status Register In the v3.0 of
+ MIV_RV32, the value of `MIMPID = 0x000540AD`. In the v3.1 of MIV_RV32, the
+ value if `MIMPID = 0xE5010301` corresponding to (E)mbedded (5)ystem(01) core
+ version (03).(01) this terminology will be followed in the subsequent releases
+ of the core read the csr value and store it in a varible which may be used to
+ check the MIV_RV32 core version during runtime.
+
+ Future releases of the core will increment the 03 and 01 as major and minor
+ releases respectively and the register can be read at runtime to find the
+ Soft IP core version.
+
+ | Core Version | Register | Value | Notes |
+ |----------------|------------|---------|---------|
+ | MIV_RV32 V3.1 | mimpid | 0xE5010301 | implimentation ID |
+ | MIV_RV32 V3.0 | mimpid | 0x000540AD | implimentation ID |
+ */
+#define MIMPID read_csr(mimpid)
+
+/*Used as a mask to read and write to mte mtvec.BASE address*/
+#define MTVEC_BASE_ADDR_MASK 0xFFFFFFFC
+
+#else
+#define MTIME (0u)
+#define MTIMEH (0u)
+#endif /*MIV_RV32_EXT_TIMER*/
+
+/*-------------------------------------------------------------------------*//**
+ RISC-V Specification Interrupts
+ =======================================
+ These definitions are provided for easy identification of the interrupt
+ 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.
+
+ All the interrups, provided by the MIV_RV32 core, follow the interrupt priority
+ order and register description as mentioned in the RISC-V spec.
+
+ | Macro Name | Value | Description|
+ |-------------------|--------|----------------|
+ | MRV32_SOFT_IRQn | MIE_3_IRQn | Software interrupt enable |
+ | MRV32_TIMER_IRQn | MIE_7_IRQn | Timer interrupt enable |
+ | MRV32_EXT_IRQn | MIE_11_IRQn | External interrupt enable |
+
+ */
+#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 0xC*/
+ MIE_4_IRQn = (0x01u<<4u),
+ MIE_5_IRQn = (0x01u<<5u),
+ MIE_6_IRQn = (0x01u<<6u),
+ MIE_7_IRQn = (0x01u<<7u), /*MTIE 0x1C*/
+ MIE_8_IRQn = (0x01u<<8u),
+ MIE_9_IRQn = (0x01u<<9u),
+ MIE_10_IRQn = (0x01u<<10u),
+ MIE_11_IRQn = (0x01u<<11u), /*MEIE 0x2C*/
+ 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 ECC Uncorrectable 0x40*/
+ MIE_17_IRQn = (0x01u<<17u), /*MGECIE ECC Correctable 0x44*/
+ 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), /*SUBSYSR 0x58 (R)eserved*/
+ MIE_23_IRQn = (0x01u<<23u), /*SUBSYS_IE 0x5C for MIV_RV32 v3.1*/
+ MIE_24_IRQn = (0x01u<<24u), /*MSYS_IE0 0x60*/
+ MIE_25_IRQn = (0x01u<<25u), /*MSYS_IE1 0x64*/
+ MIE_26_IRQn = (0x01u<<26u), /*MSYS_IE2 0x68*/
+ MIE_27_IRQn = (0x01u<<27u), /*MSYS_IE3 0x6C*/
+ MIE_28_IRQn = (0x01u<<28u), /*MSYS_IE4 0x70*/
+ MIE_29_IRQn = (0x01u<<29u), /*MSYS_IE5 0x74*/
+ MIE_30_IRQn = (0x01u<<30u), /*MSYS_IE6 0x78, read comment below*/
+ MIE_31_IRQn = (0x01u<<31u) /*MSYS_IE7 0x7C*/
+} MRV_LOCAL_IRQn_Type;
+
+#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
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define MRV32_SUBSYSR_IRQn MIE_22_IRQn
+#define MRV32_SUBSYS_IRQn MIE_23_IRQn
+#define MRV32_MSYS_EIE6_IRQn MIE_30_IRQn
+#define MRV32_MSYS_EIE7_IRQn MIE_31_IRQn
+#else
+#define MRV32_SUBSYS_IRQn MIE_30_IRQn
+#endif /*MIV_RV32_V3_0*/
+
+/*--------------------------------Public APIs---------------------------------*/
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ecc_errors() function clears single bit ECC errors on the
+ GPRs. The ECC block does not write back corrected data to memory. Hence, 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 is corrected and will not have the error, but
+ the data source will still have the error. Therefore, if data has a single bit
+ error, then the corrected data must be written back to prevent the single bit
+ error from becoming a double bit error. Clear the pending interrupt bit after
+ this using MRV32_mgeci_clear_irq() function to complete the ECC error handling.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+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));
+}
+
+
+/***************************************************************************//**
+ The MRV32_mgeui_clear_irq() function clears the GPR ECC Uncorrectable
+ Interrupt. MGEUI interrupt is available only when ECC is enabled in the MIV_RV32
+ IP configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeui_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGEUIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV32_mgeci_clear_irq() function clears the GPR ECC Correctable Interrupt
+ MGECI interrupt is available only when ECC is enabled in the MIV_RV32 IP
+ configurator.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_mgeci_clear_irq(void)
+{
+ clear_csr(mip, MRV32_MGECIE_IRQn);
+}
+
+/***************************************************************************//**
+ The MRV_enable_local_irq() function enables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_enable_local_irq(uint32_t mask)
+{
+ set_csr(mie, mask);
+}
+
+/***************************************************************************//**
+ The MRV_disable_local_irq() function disables the local interrupts. It takes a
+ mask value as input. For each set bit in the mask value, the 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_SUBSYS_IRQn);
+ */
+static inline void MRV_disable_local_irq(uint32_t mask)
+{
+ clear_csr(mie, mask);
+}
+#endif /* MIV_LEGACY_RV32 */
+
+/***************************************************************************//**
+ The MRV_enable_interrupts() function enables all interrupts by setting the
+ machine mode interrupt enable bit in MSTATUS register.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_enable_interrupts(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_disable_interrupts() function disables all interrupts by clearing the
+ machine mode interrupt enable bit in MSTATUS register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline void MRV_disable_interrupts(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/***************************************************************************//**
+ The MRV_read_mtvec_base() function reads the mtvec base value, which is the
+ addr used when an interrupt/trap occurs. In the mtvec register, [31:2] is the
+ BASE address. NOTE: The BASE address must be aligned on a 4B boundary.
+
+ @param
+ The function does not take any parameters.
+
+ @return
+ The function returns the value of the BASE field [31:2] as an unsigned 32-bit
+ value.
+ */
+
+#ifndef MIV_LEGACY_RV32
+#ifndef MIV_RV32_v3_0
+static inline uint32_t MRV_read_mtvec_base (void)
+{
+ uint32_t mtvec_addr_base = read_csr(mtvec);
+ return mtvec_addr_base & MTVEC_BASE_ADDR_MASK;
+}
+
+/***************************************************************************//**
+ The MRV_set_mtvec_base() function takes the mtvec_base address as a unsigned int
+ and writes the value into the BASE field [31:2] in the mtvec CSR, MODE[1:0]
+ is Read-only. BASE is 4B aligned, so the lowest 2 bits of mtvec_base are
+ ignored.
+
+ @param mtvec_base
+ Any legal value is passed into the function, and it is used as the trap_entry
+ for interrupts. The PC jumps to this address provided when an interrupt occurs.
+ In case of vectored interrupts, the address value mentioned in the vector
+ table under the MIE Register Map is updated to the value passed to this
+ function parameter.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV_set_mtvec_base (uint32_t mtvec_base)
+{
+ mtvec_base = mtvec_base & MTVEC_BASE_ADDR_MASK;
+ write_csr(mtvec, mtvec_base);
+}
+#endif /*MIV_RV32_v3_0*/
+#endif /*MIV_LEGACY_RV32*/
+
+/***************************************************************************//**
+ The MRV_read_mtime() function returns the current MTIME register value.
+ */
+static inline uint64_t MRV_read_mtime(void)
+{
+ volatile uint32_t hi = 0u;
+ volatile uint32_t lo = 0u;
+
+ /* 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);
+}
+
+/***************************************************************************//**
+ The MRV_raise_soft_irq() function raises a synchronous software interrupt
+ by writing into the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg |= SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ The MRV_clear_soft_irq() function clears a synchronous software interrupt
+ by clearing the MSIP register.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+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 */
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_IRQ;
+#endif
+}
+
+/***************************************************************************//**
+ System tick handler. This handler function gets called when the Machine
+ timer interrupt asserts. An implementation of this function must 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.
+
+ Though this function can take any valid ticks value as parameter, we expect
+ that, for all practical purposes, a small tick value (to generate periodic
+ interrupts every few miliseconds) is passed. If you need to generate periodic
+ events in the range of seconds or more, you may use the SysTick_Handler() to
+ further count the number of interrupts and hence the larger time intervals.
+
+ @param ticks
+ This is the number of ticks or clock cycles which are counted down from the
+ interrupt to be triggered.
+
+ @return
+ Returns 0 if successful.
+ Returns 1 if the interrupt interval is not achieved.
+ */
+uint32_t MRV_systick_config(uint64_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RISCV_HAL_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal_version.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
new file mode 100644
index 0000000..4922bf2
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_hal_version.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_hal_version.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ */
+
+#ifndef MIV_RV32_HAL_VERSION_H
+#define MIV_RV32_HAL_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MIV_RV32_HAL_VERSION_MAJOR 4
+#define MIV_RV32_HAL_VERSION_MINOR 2
+#define MIV_RV32_HAL_VERSION_PATCH 100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_init.c b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_init.c
new file mode 100644
index 0000000..85f8aca
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_init.c
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2019 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_plic.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_plic.h
new file mode 100644
index 0000000..3fd4103
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_plic.h
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include "miv_rv32_regs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+#ifdef MIV_LEGACY_RV32
+typedef enum
+{
+ MRV_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];
+} MRV_IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} MRV_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 MRV_Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ MRV_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 (MRV_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 /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_regs.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_regs.h
new file mode 100644
index 0000000..07d58e7
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_regs.h
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright 2019 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 MIV_RV32_REGS_H
+#define MIV_RV32_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)
+
+#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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_stubs.c b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_stubs.c
new file mode 100644
index 0000000..e26ecfc
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_stubs.c
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright 2019 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 SUBSYS_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI0_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI1_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI2_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI3_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI4_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI5_IRQHandler(void)
+{
+}
+__attribute__((weak)) void Reserved_IRQHandler(void)
+{
+ _exit(10);
+}
+#ifndef MIV_RV32_V3_0 /* For MIV_RV32 v3.0 */
+__attribute__((weak)) void MSYS_EI6_IRQHandler(void)
+{
+}
+__attribute__((weak)) void MSYS_EI7_IRQHandler(void)
+{
+}
+__attribute__((weak)) void SUBSYSR_IRQHandler(void)
+{
+}
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_subsys.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_subsys.h
new file mode 100644
index 0000000..509f13b
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_subsys.h
@@ -0,0 +1,293 @@
+/*******************************************************************************
+ * Copyright 2023 Microchip FPGA Embedded Systems Solutions.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * @file miv_rv32_subsys.h
+ * @author Microchip FPGA Embedded Systems Solutions
+ * @brief Mi-V soft processor SUBSYS regsiter description and API fuctions.
+ *
+ */
+#ifndef MIV_RV32_SUBSYS_H
+#define MIV_RV32_SUBSYS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#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 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 MIV_LOCAL_IRQ_MIN 16
+#ifndef MIV_RV32_V3_0 /*For MIV_RV32 v3.1*/
+#define SUBSYSR 22U
+#define SUBSYS_EI 23U
+#define MSYS_EI6 30U
+#define MSYS_EI7 31U
+#define MIV_SUBSYSR (1u << SUBSYSR)
+#define MIV_SUBSYS (1u << SUBSYS_EI)
+#define MSYS_EI6IP (1u << MSYS_EI6)
+#define MSYS_EI7IP (1u << MSYS_EI7)
+#define MIV_LOCAL_IRQ_MAX 31
+
+#else /* MIV_RV32_V3_0 */
+#define MIV_LOCAL_IRQ_MAX 29
+#define SUBSYS_EI 30U
+#define MIP_SUBSYS_REG (1u << SUBSYS_EI)
+
+#endif /* MIV_RV32_V3_0 */
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef MIV_LEGACY_RV32
+#define MIV_LOCAL_IRQ_MAX 0U
+#define MIV_LOCAL_IRQ_MIN 0U
+#endif /* MIV_LEGACY_RV32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Register Configuration
+ =======================================
+ For the SUBSYS registers configutation, the following definitions are used in
+ the SUBSUS API functions. For example, to raise soft interrupts, enable parity
+ checks, soft reset, and so on.
+
+ | Configuration | Value | Description |
+ |--------------------------|-------|------------------------------------------------|
+ | SUBSYS_SOFT_REG_GRP_DED | 0x04 | Mask for the Core GPR DED Reset Register |
+ | SUBSYS_CFG_PARITY_CHECK | 0x01 | Use to set or clear the parity check on the TCM |
+ | SUBSYS_SOFT_RESET | 0x01 | Use the SUBSYS soft reset the MIV_RV32 IP core |
+ | SUBSYS_SOFT_IRQ | 0x02 | Use to raise a software interrupt through SUBSYS|
+ */
+/*Mask for the Core GPR DED Reset Register*/
+#define SUBSYS_SOFT_REG_GRP_DED 0x04U
+
+/*Use to set or clear the parity check on the TCM*/
+#define SUBSYS_CFG_PARITY_CHECK 0x01U
+
+/*Use the SUBSYS soft reset the MIV_RV32 IP core*/
+#define SUBSYS_SOFT_RESET 0x01U
+
+/*Use to raise a software interrupt through SUBSYS*/
+#define SUBSYS_SOFT_IRQ 0x02U
+
+/*-------------------------------------------------------------------------*//**
+ SUBSYS Interrupt Request Masks
+ =======================================
+ The following values correspond to the bit value of the SUBSYS interrupt
+ enable and interrupt pending register.
+
+ | Interrupt Mask | Value | Description |
+ |----------------------------|---------|-------------------------------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u | TCM ECC controllable error irq enable |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u | TCM ECC uncontrollable error irq enable |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u | AXI write response error irq enable |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u | Icache ECC Correctable error irq |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u | Icache ECC Uncorrectable error irq |
+ | SUBSYS_BASE_ADDR | 0x6000u | Base address of the SUBSYS |
+ */
+/* TCM ECC correctable error irq enable mask value */
+#define SUBSYS_TCM_ECC_CE_IRQ 0x01u
+
+/* TCMECC uncorrectable error irq enable */
+#define SUBSYS_TCM_ECC_UCE_IRQ 0x02u
+
+/* AXI write response error irq enable */
+#define SUBSYS_AXI_WR_RESP_IRQ 0x10u
+
+/*Icache ECC Correctable error irq*/
+#define SUBSYS_ICACHE_ECC_CE_IRQ 0x40u
+
+/*Icache ECC Uncorrectable error irq*/
+#define SUBSYS_ICACHE_ECC_UCE_IRQ 0x80u
+
+/*Base address of the SUBSYS*/
+#define SUBSYS_BASE_ADDR 0x00006000UL
+
+/***************************************************************************//**
+ Subsys contains interrupt enable, interrupt pending and Subsys registers
+ which can be used to enable SUBSYS specific features such as ECC for vaious
+ memories. For more available features refer to the MIV_RV32 User Guide
+*/
+typedef struct
+{
+ volatile uint32_t cfg; /*Parity is not supported by MIV_RV32 v3.1 and MIV_RV32 v3.0.100*/
+ 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*/
+} SUBSYS_Type;
+
+#define SUBSYS ((SUBSYS_Type *)SUBSYS_BASE_ADDR)
+
+/***************************************************************************//**
+ The MRV32_subsys_enable_irq() function initializes the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to enable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_enable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_disable_irq() function disables the SUBSYS interrupts. It
+ takes the logical OR of the following defined IRQ masks as a parameter.
+
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_disable_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_en &= ~irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_clear_irq() function clears the SUBSYS interrupts, which was
+ triggered. It takes the logical OR of the following defined IRQ masks as a
+ parameter.
+ @param irq_mask
+ | irq_mask | Value |
+ |------------------------|------------|
+ | SUBSYS_TCM_ECC_CE_IRQ | 0x01u |
+ | SUBSYS_TCM_ECC_UCE_IRQ | 0x02u |
+ | SUBSYS_AXI_WR_RESP_IRQ | 0x10u |
+ | SUBSYS_ICACHE_ECC_CE_IRQ | 0x40u |
+ | SUBSYS_ICACHE_ECC_UCE_IRQ | 0x80u |
+ Use logical OR values of one or more interrupts to disable them in the SUBSYS
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_subsys_clear_irq(uint32_t irq_mask)
+{
+ SUBSYS->irq_pend |= irq_mask;
+}
+
+/***************************************************************************//**
+ The MRV32_subsys_irq_cause() function returns the irq_pend register value which
+ is present in the SUBSYS. This is be used to check which irq_mask value
+ caused the SUBSYS interrupt to occur.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function returns the irq_pend regsiter value.
+*/
+static inline uint32_t MRV32_subsys_irq_cause()
+{
+ return SUBSYS->irq_pend;
+}
+
+/***************************************************************************//**
+ The MRV32_is_gpr_ded() function 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This functions returns the CORE_GPR_DED_RESET_REG bit value.
+ */
+static inline uint32_t MRV32_is_gpr_ded(void)
+{
+ return((SUBSYS->soft_reg & SUBSYS_SOFT_REG_GRP_DED) >> 0x02u);
+}
+
+/***************************************************************************//**
+ The MRV32_clear_gpr_ded() function must 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.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_clear_gpr_ded(void)
+{
+ SUBSYS->soft_reg &= ~SUBSYS_SOFT_REG_GRP_DED;
+}
+
+/***************************************************************************//**
+ The MRV32_enable_parity_check() function is used to enable parity check on
+ the TCM and it's interface transactions. This feature is not available on
+ MIV_RV32 v3.1 and MIV_RV32 v3.0.100
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_enable_parity_check(void)
+{
+ SUBSYS->cfg |= SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_disable_parity_check() function is used to disable parity check on
+ the TCM and it's interface transactions.
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+
+ */
+static inline void MRV32_disable_parity_check(void)
+{
+ SUBSYS->cfg &= ~SUBSYS_CFG_PARITY_CHECK;
+}
+
+/***************************************************************************//**
+ The MRV32_cpu_soft_reset() function is used to cause a soft cpu reset on
+ the MIV_RV32 soft processor core.
+ @param
+ This function does not take any parameters.
+
+ @return
+ This function does not return any value.
+ */
+static inline void MRV32_cpu_soft_reset(void)
+{
+ SUBSYS->soft_reg |= SUBSYS_SOFT_RESET;
+}
+#endif /* MIV_RV32_SUBSYS_H */
\ No newline at end of file
diff --git a/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_syscall.c b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_syscall.c
new file mode 100644
index 0000000..bd2f881
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/miv_rv32_syscall.c
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * Copyright 2019 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
+#include
+
+#ifndef LEGACY_DIR_STRUCTURE
+#include "drivers/fpga_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)
+{
+ char towrite;
+
+ write( fd , "0x", 2U );
+
+ for (uint32_t ii = 8U ; ii > 0U; ii--)
+ {
+ uint32_t jj = ii-1U;
+ uint8_t 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;
+ extern char __heap_start;
+ extern char __heap_end;
+ static char *curbrk = &_end;
+ void * ret = NULL;
+
+ /*
+ * Did we allocated memory for the heap in the linker script?
+ * You need to set HEAP_SIZE to a non-zero value in your linker script if
+ * the following assertion fires.
+ */
+ ASSERT(&__heap_end > &__heap_start);
+
+ if (((curbrk + incr) < &_end) || ((curbrk + incr) > &_heap_end))
+ {
+ errno = ENOMEM;
+ ret = ((char *) - 1);
+ }
+ else
+ {
+ curbrk += incr;
+ ret = curbrk - incr;
+ }
+
+ /*
+ * Did we run out of heap?
+ * You need to increase the heap size in the linker script if the following
+ * assertion fires.
+ * */
+ ASSERT(curbrk <= &__heap_end);
+
+ 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/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/sample_fpga_design_config.h b/user-crypto/miv-rv32-message-authentication/src/platform/miv_rv32_hal/sample_fpga_design_config.h
new file mode 100644
index 0000000..a380d96
--- /dev/null
+++ b/user-crypto/miv-rv32-message-authentication/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/user-crypto/miv-rv32-ndrbg-services/.cproject b/user-crypto/miv-rv32-ndrbg-services/.cproject
new file mode 100644
index 0000000..e0d068b
--- /dev/null
+++ b/user-crypto/miv-rv32-ndrbg-services/.cproject
@@ -0,0 +1,334 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+