summaryrefslogtreecommitdiff
path: root/bsp/smartfusion2/libraries
diff options
context:
space:
mode:
authorwhik <[email protected]>2020-06-05 21:56:40 +0800
committerwhik <[email protected]>2020-06-05 21:56:40 +0800
commit02c6c92a19976b5b5269e23026bae99a82c8fab0 (patch)
treef3cfb0f2d1746ccff433d50a84a8e334385fb51b /bsp/smartfusion2/libraries
parent695a58648ad49397c106d7d1f508eb27d3bc94a7 (diff)
add support for SmartFusion2 family FPGA
Diffstat (limited to 'bsp/smartfusion2/libraries')
-rw-r--r--bsp/smartfusion2/libraries/mss_gpio/mss_gpio.c298
-rw-r--r--bsp/smartfusion2/libraries/mss_gpio/mss_gpio.h507
-rw-r--r--bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.c752
-rw-r--r--bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.h90
-rw-r--r--bsp/smartfusion2/libraries/mss_sys_services/mss_comblk_page_handler.h66
-rw-r--r--bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.c2452
-rw-r--r--bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.h2500
-rw-r--r--bsp/smartfusion2/libraries/mss_uart/mss_uart.c1762
-rw-r--r--bsp/smartfusion2/libraries/mss_uart/mss_uart.h2639
-rw-r--r--bsp/smartfusion2/libraries/mss_uart/mss_uart_regs.h83
-rw-r--r--bsp/smartfusion2/libraries/sys_config/sys_config.c385
-rw-r--r--bsp/smartfusion2/libraries/sys_config/sys_config.h66
-rw-r--r--bsp/smartfusion2/libraries/sys_config/sys_config_mss_clocks.h21
13 files changed, 11621 insertions, 0 deletions
diff --git a/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.c b/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.c
new file mode 100644
index 0000000000..11dbc21fee
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.c
@@ -0,0 +1,298 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 microcontroller subsystem GPIO bare metal driver implementation.
+ *
+ * SVN $Revision: 7749 $
+ * SVN $Date: 2015-09-04 14:32:09 +0530 (Fri, 04 Sep 2015) $
+ */
+#include "mss_gpio.h"
+#include "../../CMSIS/mss_assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ * Defines.
+ */
+#define GPIO_INT_ENABLE_MASK ((uint32_t)0x00000008uL)
+#define OUTPUT_BUFFER_ENABLE_MASK 0x00000004u
+
+#define NB_OF_GPIO ((uint32_t)32)
+
+/*-------------------------------------------------------------------------*//**
+ * Lookup table of GPIO configuration registers address indexed on GPIO ID.
+ */
+static uint32_t volatile * const g_config_reg_lut[NB_OF_GPIO] =
+{
+ &(GPIO->GPIO_0_CFG),
+ &(GPIO->GPIO_1_CFG),
+ &(GPIO->GPIO_2_CFG),
+ &(GPIO->GPIO_3_CFG),
+ &(GPIO->GPIO_4_CFG),
+ &(GPIO->GPIO_5_CFG),
+ &(GPIO->GPIO_6_CFG),
+ &(GPIO->GPIO_7_CFG),
+ &(GPIO->GPIO_8_CFG),
+ &(GPIO->GPIO_9_CFG),
+ &(GPIO->GPIO_10_CFG),
+ &(GPIO->GPIO_11_CFG),
+ &(GPIO->GPIO_12_CFG),
+ &(GPIO->GPIO_13_CFG),
+ &(GPIO->GPIO_14_CFG),
+ &(GPIO->GPIO_15_CFG),
+ &(GPIO->GPIO_16_CFG),
+ &(GPIO->GPIO_17_CFG),
+ &(GPIO->GPIO_18_CFG),
+ &(GPIO->GPIO_19_CFG),
+ &(GPIO->GPIO_20_CFG),
+ &(GPIO->GPIO_21_CFG),
+ &(GPIO->GPIO_22_CFG),
+ &(GPIO->GPIO_23_CFG),
+ &(GPIO->GPIO_24_CFG),
+ &(GPIO->GPIO_25_CFG),
+ &(GPIO->GPIO_26_CFG),
+ &(GPIO->GPIO_27_CFG),
+ &(GPIO->GPIO_28_CFG),
+ &(GPIO->GPIO_29_CFG),
+ &(GPIO->GPIO_30_CFG),
+ &(GPIO->GPIO_31_CFG)
+};
+
+/*-------------------------------------------------------------------------*//**
+ * Lookup table of Cortex-M3 GPIO interrupt number indexed on GPIO ID.
+ */
+static const IRQn_Type g_gpio_irqn_lut[NB_OF_GPIO] =
+{
+ GPIO0_IRQn,
+ GPIO1_IRQn,
+ GPIO2_IRQn,
+ GPIO3_IRQn,
+ GPIO4_IRQn,
+ GPIO5_IRQn,
+ GPIO6_IRQn,
+ GPIO7_IRQn,
+ GPIO8_IRQn,
+ GPIO9_IRQn,
+ GPIO10_IRQn,
+ GPIO11_IRQn,
+ GPIO12_IRQn,
+ GPIO13_IRQn,
+ GPIO14_IRQn,
+ GPIO15_IRQn,
+ GPIO16_IRQn,
+ GPIO17_IRQn,
+ GPIO18_IRQn,
+ GPIO19_IRQn,
+ GPIO20_IRQn,
+ GPIO21_IRQn,
+ GPIO22_IRQn,
+ GPIO23_IRQn,
+ GPIO24_IRQn,
+ GPIO25_IRQn,
+ GPIO26_IRQn,
+ GPIO27_IRQn,
+ GPIO28_IRQn,
+ GPIO29_IRQn,
+ GPIO30_IRQn,
+ GPIO31_IRQn
+};
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_init
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_init( void )
+{
+ uint32_t inc;
+
+ /* reset MSS GPIO hardware */
+ SYSREG->SOFT_RST_CR |= SYSREG_GPIO_SOFTRESET_MASK;
+ SYSREG->SOFT_RST_CR |= (SYSREG_GPIO_7_0_SOFTRESET_MASK |
+ SYSREG_GPIO_15_8_SOFTRESET_MASK |
+ SYSREG_GPIO_23_16_SOFTRESET_MASK |
+ SYSREG_GPIO_31_24_SOFTRESET_MASK);
+
+ /* Clear any previously pended MSS GPIO interrupt */
+ for(inc = 0U; inc < NB_OF_GPIO; ++inc)
+ {
+ NVIC_DisableIRQ(g_gpio_irqn_lut[inc]);
+ NVIC_ClearPendingIRQ(g_gpio_irqn_lut[inc]);
+ }
+ /* Take MSS GPIO hardware out of reset. */
+ SYSREG->SOFT_RST_CR &= ~(SYSREG_GPIO_7_0_SOFTRESET_MASK |
+ SYSREG_GPIO_15_8_SOFTRESET_MASK |
+ SYSREG_GPIO_23_16_SOFTRESET_MASK |
+ SYSREG_GPIO_31_24_SOFTRESET_MASK);
+ SYSREG->SOFT_RST_CR &= ~SYSREG_GPIO_SOFTRESET_MASK;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_config
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_config
+(
+ mss_gpio_id_t port_id,
+ uint32_t config
+)
+{
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ *(g_config_reg_lut[gpio_idx]) = config;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_set_output
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_set_output
+(
+ mss_gpio_id_t port_id,
+ uint8_t value
+)
+{
+ uint32_t gpio_setting;
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ gpio_setting = GPIO->GPIO_OUT;
+ gpio_setting &= ~((uint32_t)0x01u << gpio_idx);
+ gpio_setting |= ((uint32_t)value & 0x01u) << gpio_idx;
+ GPIO->GPIO_OUT = gpio_setting;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_drive_inout
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_drive_inout
+(
+ mss_gpio_id_t port_id,
+ mss_gpio_inout_state_t inout_state
+)
+{
+ uint32_t outputs_state;
+ uint32_t config;
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ switch(inout_state)
+ {
+ case MSS_GPIO_DRIVE_HIGH:
+ /* Set output high */
+ outputs_state = GPIO->GPIO_OUT;
+ outputs_state |= (uint32_t)1 << gpio_idx;
+ GPIO->GPIO_OUT = outputs_state;
+ /* Enable output buffer */
+ config = *(g_config_reg_lut[gpio_idx]);
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ *(g_config_reg_lut[gpio_idx]) = config;
+ break;
+
+ case MSS_GPIO_DRIVE_LOW:
+ /* Set output low */
+ outputs_state = GPIO->GPIO_OUT;
+ outputs_state &= ~((uint32_t)((uint32_t)1 << gpio_idx));
+ GPIO->GPIO_OUT = outputs_state;
+ /* Enable output buffer */
+ config = *(g_config_reg_lut[gpio_idx]);
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ *(g_config_reg_lut[gpio_idx]) = config;
+ break;
+
+ case MSS_GPIO_HIGH_Z:
+ /* Disable output buffer */
+ config = *(g_config_reg_lut[gpio_idx]);
+ config &= ~OUTPUT_BUFFER_ENABLE_MASK;
+ *(g_config_reg_lut[gpio_idx]) = config;
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_enable_irq
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_enable_irq
+(
+ mss_gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ cfg_value = *(g_config_reg_lut[gpio_idx]);
+ *(g_config_reg_lut[gpio_idx]) = (cfg_value | GPIO_INT_ENABLE_MASK);
+ NVIC_EnableIRQ(g_gpio_irqn_lut[gpio_idx]);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_disable_irq
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_disable_irq
+(
+ mss_gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ cfg_value = *(g_config_reg_lut[gpio_idx]);
+ *(g_config_reg_lut[gpio_idx]) = (cfg_value & ~GPIO_INT_ENABLE_MASK);
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * MSS_GPIO_clear_irq
+ * See "mss_gpio.h" for details of how to use this function.
+ */
+void MSS_GPIO_clear_irq
+(
+ mss_gpio_id_t port_id
+)
+{
+ uint32_t gpio_idx = (uint32_t)port_id;
+
+ ASSERT(gpio_idx < NB_OF_GPIO);
+
+ if(gpio_idx < NB_OF_GPIO)
+ {
+ GPIO->GPIO_IRQ = ((uint32_t)1) << gpio_idx;
+ }
+ __ASM volatile ("dsb");
+
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.h b/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.h
new file mode 100644
index 0000000000..58c98f8556
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_gpio/mss_gpio.h
@@ -0,0 +1,507 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 Microcontroller Subsystem GPIO bare metal software driver public
+ * API.
+ *
+ * SVN $Revision: 7748 $
+ * SVN $Date: 2015-09-04 11:36:30 +0530 (Fri, 04 Sep 2015) $
+ */
+
+/*=========================================================================*//**
+ @mainpage SmartFusion2 MSS GPIO Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The SmartFusion2 Microcontroller Subsystem (MSS) includes a block of 32 general
+ purpose input/outputs (GPIO).
+ This software driver provides a set of functions for controlling the MSS GPIO
+ block as part of a bare metal system where no operating system is available.
+ This driver 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 hw_dependencies Hardware Flow Dependencies
+ The configuration of all features of the MSS GPIOs is covered by this driver
+ with the exception of the SmartFusion2 IOMUX configuration. SmartFusion2
+ allows multiple non-concurrent uses of some external pins through IOMUX
+ configuration. This feature allows optimization of external pin usage by
+ assigning external pins for use by either the microcontroller subsystem or the
+ FPGA fabric. The MSS GPIOs share SmartFusion2 device external pins with the
+ FPGA fabric and with other MSS peripherals via an IOMUX. The MSS GPIO ports
+ can alternatively be routed to the FPGA fabric through an IOMUX.
+ The IOMUXs are configured using the SmartFusion2 MSS configurator tool. You
+ must ensure that the MSS GPIOs are enabled and configured in the SmartFusion2
+ MSS configurator if you wish to use them. For more information on IOMUXs,
+ refer to the IOMUX section of the SmartFusion2 Microcontroller Subsystem (MSS)
+ User’s Guide.
+ The base address, register addresses and interrupt number assignment for the
+ MSS GPIO block are defined as constants in the SmartFusion2 CMSIS HAL. You
+ must ensure that the latest SmartFusion2 CMSIS HAL is included in the project
+ settings of the software tool chain used to build your project and that it is
+ generated into your project.
+
+ @section theory_op Theory of Operation
+ The MSS GPIO driver functions are grouped into the following categories:
+ - Initialization
+ - Configuration
+ - Reading and setting GPIO state
+ - Interrupt control
+
+ Initialization
+ The MSS GPIO driver is initialized through a call to the MSS_GPIO_init()
+ function. The MSS_GPIO_init() function must be called before any other MSS
+ GPIO driver functions can be called.
+
+ Configuration
+ Each GPIO port is individually configured through a call to the
+ MSS_GPIO_config() function. Configuration includes deciding if a GPIO port
+ will be used as an input, an output or both. GPIO ports configured as inputs
+ can be further configured to generate interrupts based on the input's state.
+ Interrupts can be level or edge sensitive.
+
+ Reading and Setting GPIO State
+ The state of the GPIO ports can be read and set using the following functions:
+ - MSS_GPIO_get_inputs()
+ - MSS_GPIO_get_outputs()
+ - MSS_GPIO_set_outputs()
+ - MSS_GPIO_set_output()
+ - MSS_GPIO_drive_inout()
+
+ Interrupt Control
+ Interrupts generated by GPIO ports configured as inputs are controlled using
+ the following functions:
+ - MSS_GPIO_enable_irq()
+ - MSS_GPIO_disable_irq()
+ - MSS_GPIO_clear_irq()
+
+ *//*=========================================================================*/
+#ifndef MSS_GPIO_H_
+#define MSS_GPIO_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../CMSIS/m2sxxx.h"
+
+/*-------------------------------------------------------------------------*//**
+ The mss_gpio_id_t enumeration is used to identify individual GPIO ports as an
+ argument to functions:
+ - MSS_GPIO_config()
+ - MSS_GPIO_set_output() and MSS_GPIO_drive_inout()
+ - MSS_GPIO_enable_irq(), MSS_GPIO_disable_irq() and MSS_GPIO_clear_irq()
+ */
+typedef enum __mss_gpio_id_t
+{
+ MSS_GPIO_0 = 0,
+ MSS_GPIO_1 = 1,
+ MSS_GPIO_2 = 2,
+ MSS_GPIO_3 = 3,
+ MSS_GPIO_4 = 4,
+ MSS_GPIO_5 = 5,
+ MSS_GPIO_6 = 6,
+ MSS_GPIO_7 = 7,
+ MSS_GPIO_8 = 8,
+ MSS_GPIO_9 = 9,
+ MSS_GPIO_10 = 10,
+ MSS_GPIO_11 = 11,
+ MSS_GPIO_12 = 12,
+ MSS_GPIO_13 = 13,
+ MSS_GPIO_14 = 14,
+ MSS_GPIO_15 = 15,
+ MSS_GPIO_16 = 16,
+ MSS_GPIO_17 = 17,
+ MSS_GPIO_18 = 18,
+ MSS_GPIO_19 = 19,
+ MSS_GPIO_20 = 20,
+ MSS_GPIO_21 = 21,
+ MSS_GPIO_22 = 22,
+ MSS_GPIO_23 = 23,
+ MSS_GPIO_24 = 24,
+ MSS_GPIO_25 = 25,
+ MSS_GPIO_26 = 26,
+ MSS_GPIO_27 = 27,
+ MSS_GPIO_28 = 28,
+ MSS_GPIO_29 = 29,
+ MSS_GPIO_30 = 30,
+ MSS_GPIO_31 = 31
+} mss_gpio_id_t;
+
+/*-------------------------------------------------------------------------*//**
+ These constant definitions are used as an argument to the
+ MSS_GPIO_set_outputs() function to identify GPIO ports. A logical OR of these
+ constants can be used to specify multiple GPIO ports.
+ These definitions can also be used to identify GPIO ports through logical
+ operations on the return value of the MSS_GPIO_get_inputs() function.
+ */
+#define MSS_GPIO_0_MASK 0x00000001uL
+#define MSS_GPIO_1_MASK 0x00000002uL
+#define MSS_GPIO_2_MASK 0x00000004uL
+#define MSS_GPIO_3_MASK 0x00000008uL
+#define MSS_GPIO_4_MASK 0x00000010uL
+#define MSS_GPIO_5_MASK 0x00000020uL
+#define MSS_GPIO_6_MASK 0x00000040uL
+#define MSS_GPIO_7_MASK 0x00000080uL
+#define MSS_GPIO_8_MASK 0x00000100uL
+#define MSS_GPIO_9_MASK 0x00000200uL
+#define MSS_GPIO_10_MASK 0x00000400uL
+#define MSS_GPIO_11_MASK 0x00000800uL
+#define MSS_GPIO_12_MASK 0x00001000uL
+#define MSS_GPIO_13_MASK 0x00002000uL
+#define MSS_GPIO_14_MASK 0x00004000uL
+#define MSS_GPIO_15_MASK 0x00008000uL
+#define MSS_GPIO_16_MASK 0x00010000uL
+#define MSS_GPIO_17_MASK 0x00020000uL
+#define MSS_GPIO_18_MASK 0x00040000uL
+#define MSS_GPIO_19_MASK 0x00080000uL
+#define MSS_GPIO_20_MASK 0x00100000uL
+#define MSS_GPIO_21_MASK 0x00200000uL
+#define MSS_GPIO_22_MASK 0x00400000uL
+#define MSS_GPIO_23_MASK 0x00800000uL
+#define MSS_GPIO_24_MASK 0x01000000uL
+#define MSS_GPIO_25_MASK 0x02000000uL
+#define MSS_GPIO_26_MASK 0x04000000uL
+#define MSS_GPIO_27_MASK 0x08000000uL
+#define MSS_GPIO_28_MASK 0x10000000uL
+#define MSS_GPIO_29_MASK 0x20000000uL
+#define MSS_GPIO_30_MASK 0x40000000uL
+#define MSS_GPIO_31_MASK 0x80000000uL
+
+/*-------------------------------------------------------------------------*//**
+ These constant definitions are used as an argument to the MSS_GPIO_config()
+ function to specify the I/O mode of each GPIO port.
+ */
+#define MSS_GPIO_INPUT_MODE 0x0000000002uL
+#define MSS_GPIO_OUTPUT_MODE 0x0000000005uL
+#define MSS_GPIO_INOUT_MODE 0x0000000003uL
+
+/*-------------------------------------------------------------------------*//**
+ These constant definitions are used as an argument to the MSS_GPIO_config()
+ function to specify the interrupt mode of each GPIO port.
+ */
+#define MSS_GPIO_IRQ_LEVEL_HIGH 0x0000000000uL
+#define MSS_GPIO_IRQ_LEVEL_LOW 0x0000000020uL
+#define MSS_GPIO_IRQ_EDGE_POSITIVE 0x0000000040uL
+#define MSS_GPIO_IRQ_EDGE_NEGATIVE 0x0000000060uL
+#define MSS_GPIO_IRQ_EDGE_BOTH 0x0000000080uL
+
+/*-------------------------------------------------------------------------*//**
+ The mss_gpio_inout_state_t enumeration is used to specify the output state of
+ an INOUT GPIO port as an argument to the MSS_GPIO_drive_inout() function.
+ */
+typedef enum mss_gpio_inout_state
+{
+ MSS_GPIO_DRIVE_LOW = 0,
+ MSS_GPIO_DRIVE_HIGH,
+ MSS_GPIO_HIGH_Z
+} mss_gpio_inout_state_t;
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_init() function initializes the SmartFusion2 MSS GPIO block. It
+ resets the MSS GPIO hardware block and it also clears any pending MSS GPIO
+ interrupts in the ARM Cortex-M3 interrupt controller. When the function exits,
+ it takes the MSS GPIO block out of reset.
+
+ @param
+ This function has no parameters.
+
+ @return
+ This function does not return a value.
+ */
+void MSS_GPIO_init( void );
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_config() function is used to configure an individual GPIO port.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port to be configured. An
+ enumeration item of the form MSS_GPIO_n, where n is the number of the GPIO
+ port, is used to identify the GPIO port. For example, MSS_GPIO_0 identifies
+ the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @param config
+ The config parameter specifies the configuration to be applied to the GPIO
+ port identified by the port_id parameter. It is a logical OR of the required
+ I/O mode and the required interrupt mode. The interrupt mode is not relevant
+ if the GPIO is configured as an output only.
+ These I/O mode constants are allowed:
+ - MSS_GPIO_INPUT_MODE
+ - MSS_GPIO_OUTPUT_MODE
+ - MSS_GPIO_INOUT_MODE
+ These interrupt mode constants are allowed:
+ - MSS_GPIO_IRQ_LEVEL_HIGH
+ - MSS_GPIO_IRQ_LEVEL_LOW
+ - MSS_GPIO_IRQ_EDGE_POSITIVE
+ - MSS_GPIO_IRQ_EDGE_NEGATIVE
+ - MSS_GPIO_IRQ_EDGE_BOTH
+
+ @return
+ none.
+
+ Example:
+ The following call will configure GPIO 4 as an input generating interrupts on
+ a Low to High transition of the input:
+ @code
+ MSS_GPIO_config( MSS_GPIO_4, MSS_GPIO_INPUT_MODE | MSS_GPIO_IRQ_EDGE_POSITIVE );
+ @endcode
+ */
+void MSS_GPIO_config
+(
+ mss_gpio_id_t port_id,
+ uint32_t config
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_set_outputs() function is used to set the state of all GPIO ports
+ configured as outputs.
+
+ @param value
+ The value parameter specifies the state of the GPIO ports configured as
+ outputs. It is a bit mask of the form (MSS_GPIO_n_MASK | MSS_GPIO_m_MASK)
+ where n and m are numbers identifying GPIOs. For example, (MSS_GPIO_0_MASK |
+ MSS_GPIO_1_MASK | MSS_GPIO_2_MASK ) specifies that the first, second and
+ third GPIO outputs must be set High and all other GPIO outputs set Low. The
+ driver provides 32 mask constants, MSS_GPIO_0_MASK to MSS_GPIO_31_MASK
+ inclusive, for this purpose.
+
+ @return
+ none.
+
+ Example 1:
+ Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.
+ @code
+ MSS_GPIO_set_outputs( MSS_GPIO_0_MASK | MSS_GPIO_8_MASK );
+ @endcode
+
+ Example 2:
+ Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.
+ @code
+ uint32_t gpio_outputs;
+ gpio_outputs = MSS_GPIO_get_outputs();
+ gpio_outputs &= ~( MSS_GPIO_2_MASK | MSS_GPIO_4_MASK );
+ MSS_GPIO_set_outputs( gpio_outputs );
+ @endcode
+
+ @see MSS_GPIO_get_outputs()
+ */
+static __INLINE void
+MSS_GPIO_set_outputs
+(
+ uint32_t value
+)
+{
+ GPIO->GPIO_OUT = value;
+}
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_set_output() function is used to set the state of a single GPIO
+ port configured as an output.
+ Note: Using bit-band writes might be a better option than this function for
+ performance critical applications where the application code is not
+ intended to be ported to a processor other than the ARM Cortex-M3 in
+ SmartFusion2. The bit-band write equivalent to this function would be:
+ GPIO_BITBAND->GPIO_OUT[port_id] = (uint32_t)value;
+
+ @param port_id
+ The port_id parameter identifies the GPIO port that is to have its output
+ set. An enumeration item of the form MSS_GPIO_n, where n is the number of
+ the GPIO port, is used to identify the GPIO port. For example, MSS_GPIO_0
+ identifies the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @param value
+ The value parameter specifies the desired state for the GPIO output. A value
+ of 0 will set the output Low and a value of 1 will set the output High.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ The following call will set GPIO output 12 High, leaving all other GPIO
+ outputs unaffected:
+ @code
+ _GPIO_set_output(MSS_GPIO_12, 1);
+ @endcode
+ */
+void MSS_GPIO_set_output
+(
+ mss_gpio_id_t port_id,
+ uint8_t value
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_get_inputs() function is used to read the current state all GPIO
+ ports configured as inputs.
+
+ @return
+ This function returns a 32-bit unsigned integer where each bit represents
+ the state of a GPIO input. The least significant bit represents the state of
+ GPIO input 0 and the most significant bit the state of GPIO input 31.
+
+ Example:
+ Read and assign the current state of the GPIO outputs to a variable.
+ @code
+ uint32_t gpio_inputs;
+ gpio_inputs = MSS_GPIO_get_inputs();
+ @endcode
+ */
+static __INLINE uint32_t
+MSS_GPIO_get_inputs( void )
+{
+ return GPIO->GPIO_IN;
+}
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_get_outputs() function is used to read the current state all GPIO
+ ports configured as outputs.
+
+ @return
+ This function returns a 32-bit unsigned integer where each bit represents
+ the state of a GPIO output. The least significant bit represents the state
+ of GPIO output 0 and the most significant bit the state of GPIO output 31.
+
+ Example:
+ Read and assign the current state of the GPIO outputs to a variable.
+ @code
+ uint32_t gpio_outputs;
+ gpio_outputs = MSS_GPIO_get_outputs();
+ @endcode
+ */
+static __INLINE uint32_t
+MSS_GPIO_get_outputs( void )
+{
+ return GPIO->GPIO_OUT;
+}
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_drive_inout() function is used to set the output state of a
+ single GPIO port configured as an INOUT. An INOUT GPIO can be in one of three
+ states:
+ - High
+ - Low
+ - High impedance
+ An INOUT output would typically be used where several devices can drive the
+ state of a shared signal line. 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 its output state onto the
+ signal line, while at the same time allowing the input state of the GPIO to
+ be read.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port for which you want to change
+ the output state. An enumeration item of the form MSS_GPIO_n, where n is the
+ number of the GPIO port, is used to identify the GPIO port. For example,
+ MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @param inout_state
+ The inout_state parameter specifies the state of the GPIO port identified by
+ the port_id parameter. Allowed values of type mss_gpio_inout_state_t are as
+ follows:
+ - MSS_GPIO_DRIVE_HIGH
+ - MSS_GPIO_DRIVE_LOW
+ - MSS_GPIO_HIGH_Z (High impedance)
+
+ @return
+ This function does not return a value.
+
+ Example:
+ The call to MSS_GPIO_drive_inout() below will set the GPIO 7 output to the
+ high impedance state.
+ @code
+ MSS_GPIO_drive_inout( MSS_GPIO_7, MSS_GPIO_HIGH_Z );
+ @endcode
+ */
+void MSS_GPIO_drive_inout
+(
+ mss_gpio_id_t port_id,
+ mss_gpio_inout_state_t inout_state
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_enable_irq() function is used to enable interrupt generation for
+ the specified GPIO input. Interrupts are generated based on the state of the
+ GPIO input and the interrupt mode configured for it by MSS_GPIO_config().
+
+ @param port_id
+ The port_id parameter identifies the GPIO port for which you want to enable
+ interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
+ the number of the GPIO port, is used to identify the GPIO port. For example,
+ MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ The call to MSS_GPIO_enable_irq() below will allow GPIO 8 to generate
+ interrupts.
+ @code
+ MSS_GPIO_enable_irq( MSS_GPIO_8 );
+ @endcode
+ */
+void MSS_GPIO_enable_irq
+(
+ mss_gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_disable_irq() function is used to disable interrupt generation
+ for the specified GPIO input.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port for which you want to disable
+ interrupt generation. An enumeration item of the form MSS_GPIO_n, where n is
+ the number of the GPIO port, is used to identify the GPIO port. For example,
+ MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ The call to MSS_GPIO_disable_irq() below will prevent GPIO 8 from generating
+ interrupts.
+ @code
+ MSS_GPIO_disable_irq( MSS_GPIO_8 );
+ @endcode
+ */
+void MSS_GPIO_disable_irq
+(
+ mss_gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_GPIO_clear_irq() function is used to clear a pending interrupt from
+ the specified GPIO input.
+ Note: The MSS_GPIO_clear_irq() function must be called as part of any GPIO
+ interrupt service routine (ISR) in order to prevent the same interrupt
+ event retriggering a call to the GPIO ISR.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port for which you want to clear
+ the interrupt. An enumeration item of the form MSS_GPIO_n, where n is the
+ number of the GPIO port, is used to identify the GPIO port. For example,
+ MSS_GPIO_0 identifies the first GPIO port and MSS_GPIO_31 is the last one.
+
+ @return
+ none.
+
+ Example:
+ The example below demonstrates the use of the MSS_GPIO_clear_irq() function
+ as part of the GPIO 9 interrupt service routine.
+ @code
+ void GPIO9_IRQHandler( void )
+ {
+ do_interrupt_processing();
+
+ MSS_GPIO_clear_irq( MSS_GPIO_9 );
+ }
+ @endcode
+ */
+void MSS_GPIO_clear_irq
+(
+ mss_gpio_id_t port_id
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MSS_GPIO_H_ */
diff --git a/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.c b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.c
new file mode 100644
index 0000000000..ebd9805ca2
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.c
@@ -0,0 +1,752 @@
+/*******************************************************************************
+ * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 COMBLK access functions.
+ *
+ * SVN $Revision: 8345 $
+ * SVN $Date: 2016-03-23 11:53:04 +0530 (Wed, 23 Mar 2016) $
+ */
+
+#include "mss_comblk.h"
+#include "../../CMSIS/mss_assert.h"
+
+/*==============================================================================
+ *
+ */
+/*------------------------------------------------------------------------------
+ * Control register bit masks.
+ */
+#define CR_FLUSHOUT_MASK 0x01u
+#define CR_FLUSHIN_MASK 0x02u
+#define CR_SIZETX_MASK 0x04u
+#define CR_ENABLE_MASK 0x10u
+#define CR_LOOPBACK_MASK 0x20u
+
+/*------------------------------------------------------------------------------
+ * Status and interrupt enable registers bit masks.
+ */
+#define TXTOKAY_MASK 0x01u
+#define RCVOKAY_MASK 0x02u
+#define TXOVERFLOW_MASK 0x04u
+#define RXUNDERFLOW_MASK 0x08u
+/*------------------------------------------------------------------------------
+ * DATA8 register bit masks.
+ */
+#define DATA8_COMMAND_MASK 0x8000u
+
+/*------------------------------------------------------------------------------
+ * COMBLK driver states.
+ */
+#define COMBLK_IDLE 0u
+#define COMBLK_TX_CMD 1u
+#define COMBLK_TX_DATA 2u
+#define COMBLK_WAIT_RESPONSE 3u
+#define COMBLK_RX_RESPONSE 4u
+#define COMBLK_TX_PAGED_DATA 5u
+
+#define POR_DIGEST_ERROR_OPCODE 0xF1u
+
+/*==============================================================================
+ * COMBLK interrupt service routine.
+ */
+void ComBlk_IRQHandler(void);
+
+/*==============================================================================
+ * Local functions.
+ */
+static void abort_current_cmd(void);
+static void send_cmd_opcode(uint8_t opcode);
+static uint32_t fill_tx_fifo(const uint8_t * p_cmd, uint32_t cmd_size);
+static void handle_tx_okay_irq(void);
+static void handle_rx_okay_irq(void);
+static void complete_request(uint16_t response_length);
+static void process_sys_ctrl_command(uint8_t cmd_opcode);
+
+/*==============================================================================
+ * Global variables:
+ */
+static volatile uint8_t g_comblk_cmd_opcode = 0u;
+static const uint8_t * g_comblk_p_cmd = 0u;
+static volatile uint16_t g_comblk_cmd_size = 0u;
+static const uint8_t * g_comblk_p_data = 0u;
+static volatile uint32_t g_comblk_data_size = 0u;
+static uint8_t * g_comblk_p_response = 0u;
+static uint16_t g_comblk_response_size = 0u;
+static volatile uint16_t g_comblk_response_idx = 0u;
+static comblk_completion_handler_t g_comblk_completion_handler = 0;
+static uint32_t (*g_comblk_page_handler)(uint8_t const ** pp_next_page) = 0;
+static volatile uint8_t g_request_in_progress = 0u;
+static uint8_t g_comblk_state = COMBLK_IDLE;
+static volatile comblk_async_event_handler_t g_async_event_handler = 0;
+
+/*==============================================================================
+ *
+ */
+void MSS_COMBLK_init
+(
+ comblk_async_event_handler_t async_event_handler,
+ uint8_t* p_response
+)
+{
+ /*
+ * Disable and clear previous interrupts.
+ */
+ NVIC_DisableIRQ(ComBlk_IRQn);
+ COMBLK->INT_ENABLE = 0u;
+ NVIC_ClearPendingIRQ(ComBlk_IRQn);
+
+ g_async_event_handler = async_event_handler;
+
+ /*
+ * Initialize COMBLK driver state variables:
+ */
+ g_request_in_progress = 0u;
+ g_comblk_cmd_opcode = 0u;
+ g_comblk_p_cmd = 0u;
+ g_comblk_cmd_size = 0u;
+ g_comblk_p_data = 0u;
+ g_comblk_data_size = 0u;
+ g_comblk_p_response = p_response;
+ g_comblk_response_size = 0u;
+ g_comblk_response_idx = 0u;
+ g_comblk_completion_handler = 0;
+
+ g_comblk_state = COMBLK_IDLE;
+
+ /*
+ * Disable loopback before enabling the MSS COMM_BLK to ensure that any
+ * codes waiting in the TX FIFO of the System Controller�s COMM_BLK are
+ * not lost.
+ */
+ COMBLK->CONTROL &= ~CR_LOOPBACK_MASK;
+ COMBLK->CONTROL |= CR_ENABLE_MASK;
+
+ /*--------------------------------------------------------------------------
+ * Enable receive interrupt to receive asynchronous events from the system
+ * controller.
+ */
+ COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
+ COMBLK->INT_ENABLE |= RCVOKAY_MASK;
+ NVIC_EnableIRQ(ComBlk_IRQn);
+}
+
+/*==============================================================================
+ *
+ */
+void MSS_COMBLK_send_cmd_with_ptr
+(
+ uint8_t cmd_opcode,
+ uint32_t cmd_params_ptr,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_completion_handler_t completion_handler
+)
+{
+ uint32_t tx_okay;
+
+ /*--------------------------------------------------------------------------
+ * Disable and clear previous interrupts.
+ */
+ NVIC_DisableIRQ(ComBlk_IRQn);
+ COMBLK->INT_ENABLE = 0u;
+ NVIC_ClearPendingIRQ(ComBlk_IRQn);
+
+ /*--------------------------------------------------------------------------
+ * Abort current command if any.
+ */
+ abort_current_cmd();
+
+ /*--------------------------------------------------------------------------
+ * Initialize COMBLK driver state variables.
+ */
+ g_request_in_progress = 1u;
+ g_comblk_cmd_opcode = cmd_opcode;
+ g_comblk_p_cmd = 0u;
+ g_comblk_cmd_size = 0u;
+ g_comblk_p_data = 0u;
+ g_comblk_data_size = 0u;
+ g_comblk_p_response = p_response;
+ g_comblk_response_size = response_size;
+ g_comblk_response_idx = 0u;
+ g_comblk_page_handler = 0u;
+ g_comblk_completion_handler = completion_handler;
+
+ /*--------------------------------------------------------------------------
+ * Send command opcode as a single byte write to the Tx FIFO.
+ */
+ send_cmd_opcode(g_comblk_cmd_opcode);
+
+ /*--------------------------------------------------------------------------
+ * Send the command parameters pointer to the Tx FIFO as a single 4 bytes
+ * write to the Tx FIFO.
+ */
+ COMBLK->CONTROL |= CR_SIZETX_MASK;
+
+ /* Wait for space to become available in Tx FIFO. */
+ do {
+ tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
+ } while(0u == tx_okay);
+
+ /* Send command opcode. */
+ COMBLK->DATA32 = cmd_params_ptr;
+
+ COMBLK->CONTROL &= ~CR_SIZETX_MASK;
+
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+
+ /*--------------------------------------------------------------------------
+ * Enable interrupt.
+ */
+ COMBLK->INT_ENABLE |= RCVOKAY_MASK;
+ NVIC_EnableIRQ(ComBlk_IRQn);
+}
+
+/*==============================================================================
+ *
+ */
+void MSS_COMBLK_send_cmd
+(
+ const uint8_t * p_cmd,
+ uint16_t cmd_size,
+ const uint8_t * p_data,
+ uint32_t data_size,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_completion_handler_t completion_handler
+)
+{
+ uint32_t size_sent;
+
+ ASSERT(cmd_size > 0);
+
+ /*
+ * Disable and clear previous interrupts.
+ */
+ NVIC_DisableIRQ(ComBlk_IRQn);
+ COMBLK->INT_ENABLE = 0u;
+ NVIC_ClearPendingIRQ(ComBlk_IRQn);
+
+ /*
+ * Abort current command if any.
+ */
+ abort_current_cmd();
+
+ /*
+ * Initialize COMBLK driver state variables:
+ */
+ g_request_in_progress = 1u;
+ g_comblk_cmd_opcode = p_cmd[0];
+ g_comblk_p_cmd = p_cmd;
+ g_comblk_cmd_size = cmd_size;
+ g_comblk_p_data = p_data;
+ g_comblk_data_size = data_size;
+ g_comblk_p_response = p_response;
+ g_comblk_response_size = response_size;
+ g_comblk_response_idx = 0u;
+ g_comblk_page_handler = 0u;
+ g_comblk_completion_handler = completion_handler;
+
+ COMBLK->INT_ENABLE |= RCVOKAY_MASK;
+
+ /*
+ * Fill FIFO with command.
+ */
+ send_cmd_opcode(g_comblk_cmd_opcode);
+ size_sent = fill_tx_fifo(&p_cmd[1], cmd_size - 1u);
+ ++size_sent; /* Adjust for opcode byte sent. */
+ if(size_sent < cmd_size)
+ {
+ g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
+ g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
+
+ g_comblk_state = COMBLK_TX_CMD;
+ }
+ else
+ {
+ g_comblk_cmd_size = 0u;
+ if(g_comblk_data_size > 0u)
+ {
+ g_comblk_state = COMBLK_TX_DATA;
+ }
+ else
+ {
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+ }
+ }
+
+ /*
+ * Enable interrupt.
+ */
+ NVIC_EnableIRQ(ComBlk_IRQn);
+}
+
+/*==============================================================================
+ *
+ */
+void MSS_COMBLK_send_paged_cmd
+(
+ const uint8_t * p_cmd,
+ uint16_t cmd_size,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_page_handler_t page_read_handler,
+ comblk_completion_handler_t completion_handler
+)
+{
+ uint32_t size_sent;
+ uint8_t irq_enable = 0u;
+
+ ASSERT(cmd_size > 0u);
+
+ /*
+ * Disable and clear previous interrupts.
+ */
+ NVIC_DisableIRQ(ComBlk_IRQn);
+ COMBLK->INT_ENABLE = 0u;
+ NVIC_ClearPendingIRQ(ComBlk_IRQn);
+
+ /*
+ * Abort current command if any.
+ */
+ abort_current_cmd();
+
+ /*
+ * Initialize COMBLK driver state variables:
+ */
+ g_request_in_progress = 1u;
+ g_comblk_cmd_opcode = p_cmd[0];
+ g_comblk_p_cmd = p_cmd;
+ g_comblk_cmd_size = cmd_size;
+ g_comblk_p_data = 0;
+ g_comblk_data_size = 0u;
+ g_comblk_p_response = p_response;
+ g_comblk_response_size = response_size;
+ g_comblk_response_idx = 0u;
+ g_comblk_page_handler = page_read_handler;
+ g_comblk_completion_handler = completion_handler;
+
+ /*
+ * Fill FIFO with command.
+ */
+ send_cmd_opcode(g_comblk_cmd_opcode);
+ size_sent = fill_tx_fifo(&p_cmd[1], cmd_size - 1u);
+ ++size_sent; /* Adjust for opcode byte sent. */
+ if(size_sent < cmd_size)
+ {
+ g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
+ g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
+
+ g_comblk_state = COMBLK_TX_CMD;
+ irq_enable = TXTOKAY_MASK | RCVOKAY_MASK;
+ }
+ else
+ {
+ g_comblk_cmd_size = 0u;
+ g_comblk_state = COMBLK_TX_PAGED_DATA;
+ irq_enable = TXTOKAY_MASK | RCVOKAY_MASK;
+ }
+
+ /*
+ * Enable interrupt.
+ */
+ COMBLK->INT_ENABLE |= irq_enable;
+ NVIC_EnableIRQ(ComBlk_IRQn);
+}
+
+/*==============================================================================
+ * COMBLK interrupt handler.
+ */
+void ComBlk_IRQHandler(void)
+{
+ uint8_t status;
+ uint8_t tx_okay;
+ uint8_t rcv_okay;
+
+ status = (uint8_t)COMBLK->STATUS;
+
+ /* Mask off interrupt that are not enabled.*/
+ status &= COMBLK->INT_ENABLE;
+
+ rcv_okay = status & RCVOKAY_MASK;
+
+ if(rcv_okay)
+ {
+ handle_rx_okay_irq();
+ }
+
+ tx_okay = status & TXTOKAY_MASK;
+ if(tx_okay)
+ {
+ handle_tx_okay_irq();
+ }
+}
+
+/*==============================================================================
+ *
+ */
+static void handle_tx_okay_irq(void)
+{
+ switch(g_comblk_state)
+ {
+ /*----------------------------------------------------------------------
+ * The TX_OKAY interrupt should only be enabled for states COMBLK_TX_CMD
+ * and COMBLK_TX_DATA.
+ */
+ case COMBLK_TX_CMD:
+ if(g_comblk_cmd_size > 0u)
+ {
+ uint32_t size_sent;
+ size_sent = fill_tx_fifo(g_comblk_p_cmd, g_comblk_cmd_size);
+ if(size_sent < g_comblk_cmd_size)
+ {
+ g_comblk_cmd_size = g_comblk_cmd_size - (uint16_t)size_sent;
+ g_comblk_p_cmd = &g_comblk_p_cmd[size_sent];
+ }
+ else
+ {
+ g_comblk_cmd_size = 0u;
+ if(g_comblk_data_size > 0u)
+ {
+ g_comblk_state = COMBLK_TX_DATA;
+ }
+ else
+ {
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * This is an invalid situation indicating a bug in the driver
+ * or corrupted memory.
+ */
+ ASSERT(0);
+ abort_current_cmd();
+ }
+ break;
+
+ case COMBLK_TX_DATA:
+ if(g_comblk_data_size > 0u)
+ {
+ uint32_t size_sent;
+ size_sent = fill_tx_fifo(g_comblk_p_data, g_comblk_data_size);
+ if(size_sent < g_comblk_data_size)
+ {
+ g_comblk_data_size = g_comblk_data_size - size_sent;
+ g_comblk_p_data = &g_comblk_p_data[size_sent];
+ }
+ else
+ {
+ COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+ }
+ }
+ else
+ {
+ /*
+ * This is an invalid situation indicating a bug in the driver
+ * or corrupted memory.
+ */
+ ASSERT(0);
+ abort_current_cmd();
+ }
+ break;
+
+ case COMBLK_TX_PAGED_DATA:
+ /*
+ * Read a page of data if required.
+ */
+ if(0u == g_comblk_data_size)
+ {
+ if(g_comblk_page_handler != 0)
+ {
+ g_comblk_data_size = g_comblk_page_handler(&g_comblk_p_data);
+ if(0u == g_comblk_data_size)
+ {
+ COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+ }
+ }
+ else
+ {
+ ASSERT(0);
+ abort_current_cmd();
+ }
+ }
+
+ /*
+ * Transmit the page data or move to COMBLK_WAIT_RESPONSE state if
+ * no further page data could be obtained by the call to the page
+ * handler above.
+ */
+ if(0u == g_comblk_data_size)
+ {
+ COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
+ g_comblk_state = COMBLK_WAIT_RESPONSE;
+ }
+ else
+ {
+ uint32_t size_sent;
+ size_sent = fill_tx_fifo(g_comblk_p_data, g_comblk_data_size);
+ g_comblk_data_size = g_comblk_data_size - size_sent;
+ g_comblk_p_data = &g_comblk_p_data[size_sent];
+ }
+ break;
+
+ /*----------------------------------------------------------------------
+ * The TX_OKAY interrupt should NOT be enabled for states COMBLK_IDLE,
+ * COMBLK_WAIT_RESPONSE and COMBLK_RX_RESPONSE.
+ */
+ case COMBLK_IDLE:
+ /* Fall through */
+ case COMBLK_WAIT_RESPONSE:
+ /* Fall through */
+ case COMBLK_RX_RESPONSE:
+ /* Fall through */
+ default:
+ COMBLK->INT_ENABLE &= ~TXTOKAY_MASK;
+ complete_request(0u);
+ g_comblk_state = COMBLK_IDLE;
+ break;
+ }
+}
+
+/*==============================================================================
+ *
+ */
+static void handle_rx_okay_irq(void)
+{
+ uint16_t data16;
+ uint16_t is_command;
+ uint8_t data8;
+
+ data16 = (uint16_t)COMBLK->DATA8;
+ is_command = data16 & DATA8_COMMAND_MASK;
+ data8 = (uint8_t)data16;
+
+ switch(g_comblk_state)
+ {
+ /*----------------------------------------------------------------------
+ * MSS_COMBLK_init() enables the RCV_OKAY interrupt for the COMBLK_IDLE
+ * state to receive the asynchronous power-on-reset from the system
+ * controller.
+ */
+ case COMBLK_IDLE:
+ if(is_command)
+ {
+ if(data8 != POR_DIGEST_ERROR_OPCODE)
+ {
+ uint8_t rxed_opcode;
+ rxed_opcode = data8;
+ process_sys_ctrl_command(rxed_opcode);
+ }
+ else
+ {
+ g_comblk_response_idx = 0;
+ g_comblk_p_response[g_comblk_response_idx] = data8;
+ g_comblk_response_idx++;
+ g_comblk_p_response[g_comblk_response_idx] = 0x00u;
+ g_comblk_state = COMBLK_RX_RESPONSE;
+ }
+ }
+ break;
+
+ /*----------------------------------------------------------------------
+ * The RCV_OKAY interrupt should only be enabled for states
+ * COMBLK_WAIT_RESPONSE and COMBLK_RX_RESPONSE.
+ */
+ case COMBLK_WAIT_RESPONSE:
+ if(is_command)
+ {
+ uint8_t rxed_opcode;
+ rxed_opcode = data8;
+ if(rxed_opcode == g_comblk_cmd_opcode)
+ {
+ g_comblk_response_idx = 0u;
+ g_comblk_p_response[g_comblk_response_idx] = rxed_opcode;
+ ++g_comblk_response_idx;
+ g_comblk_state = COMBLK_RX_RESPONSE;
+ }
+ else
+ {
+ process_sys_ctrl_command(rxed_opcode);
+ }
+ }
+ break;
+
+ case COMBLK_RX_RESPONSE:
+ if(is_command)
+ {
+ uint8_t rxed_opcode;
+ rxed_opcode = data8;
+ process_sys_ctrl_command(rxed_opcode);
+ }
+ else
+ {
+ if( g_comblk_p_response[g_comblk_response_idx-1] == POR_DIGEST_ERROR_OPCODE)
+ {
+ g_comblk_p_response[g_comblk_response_idx] = data8;
+ process_sys_ctrl_command(g_comblk_p_response[g_comblk_response_idx-1]);
+ g_comblk_state = COMBLK_IDLE;
+ }
+ else
+ {
+ if(g_comblk_response_idx < g_comblk_response_size)
+ {
+ uint8_t rxed_data;
+
+ rxed_data = data8;
+ g_comblk_p_response[g_comblk_response_idx] = rxed_data;
+ ++g_comblk_response_idx;
+ }
+
+ if(g_comblk_response_idx == g_comblk_response_size)
+ {
+ complete_request(g_comblk_response_idx);
+ g_comblk_state = COMBLK_IDLE;
+ }
+ }
+ }
+ break;
+
+ /*----------------------------------------------------------------------
+ * The RCV_OKAY interrupt should NOT be enabled for states
+ * COMBLK_IDLE, COMBLK_TX_CMD and COMBLK_TX_DATA.
+ */
+ case COMBLK_TX_PAGED_DATA:
+ /* This is needed because when there is an error, we need to terminate loading the data */
+ if(!is_command)
+ {
+ g_comblk_p_response[1] = data8;
+ complete_request(2u);
+ g_comblk_state = COMBLK_IDLE;
+ }
+ else
+ {
+ uint8_t rxed_opcode;
+ rxed_opcode = data8;
+ process_sys_ctrl_command(rxed_opcode);
+ }
+ break;
+
+ case COMBLK_TX_CMD:
+ /* Fall through */
+ case COMBLK_TX_DATA:
+ /* Fall through */
+ if(is_command)
+ {
+ uint8_t rxed_opcode;
+ rxed_opcode = data8;
+ process_sys_ctrl_command(rxed_opcode);
+ }
+ break;
+
+ default:
+ complete_request(0u);
+ g_comblk_state = COMBLK_IDLE;
+ break;
+ }
+}
+
+/*==============================================================================
+ *
+ */
+static void complete_request
+(
+ uint16_t response_length
+)
+{
+ if(g_comblk_completion_handler != 0)
+ {
+ g_comblk_completion_handler(g_comblk_p_response, response_length);
+ g_comblk_completion_handler = 0;
+ g_request_in_progress = 0u;
+ }
+}
+
+/*==============================================================================
+ *
+ */
+static void abort_current_cmd(void)
+{
+ if(g_request_in_progress)
+ {
+ uint32_t flush_in_progress;
+
+ /*
+ * Call completion handler just in case we are in a multi threaded system
+ * to avoid a task lockup.
+ */
+ complete_request(g_comblk_response_idx);
+
+ /*
+ * Flush the FIFOs
+ */
+ COMBLK->CONTROL |= CR_FLUSHOUT_MASK;
+ do {
+ flush_in_progress = COMBLK->CONTROL & CR_FLUSHOUT_MASK;
+ } while(flush_in_progress);
+ }
+}
+
+/*==============================================================================
+ *
+ */
+static void send_cmd_opcode
+(
+ uint8_t opcode
+)
+{
+ uint32_t tx_okay;
+
+ /* Set transmit FIFO to transfer bytes. */
+ COMBLK->CONTROL &= ~CR_SIZETX_MASK;
+
+ /* Wait for space to become available in Tx FIFO. */
+ do {
+ tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
+ } while(0u == tx_okay);
+
+ /* Send command opcode. */
+ COMBLK->FRAME_START8 = opcode;
+}
+
+/*==============================================================================
+ *
+ */
+static uint32_t fill_tx_fifo
+(
+ const uint8_t * p_cmd,
+ uint32_t cmd_size
+)
+{
+ volatile uint32_t tx_okay;
+ uint32_t size_sent;
+
+ /* Set transmit FIFO to transfer bytes. */
+ COMBLK->CONTROL &= ~CR_SIZETX_MASK;
+
+ size_sent = 0u;
+ tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
+ while((tx_okay != 0u) && (size_sent < cmd_size))
+ {
+ COMBLK->DATA8 = p_cmd[size_sent];
+ ++size_sent;
+ tx_okay = COMBLK->STATUS & TXTOKAY_MASK;
+ }
+
+ return size_sent;
+}
+
+/*==============================================================================
+ *
+ */
+static void process_sys_ctrl_command(uint8_t cmd_opcode)
+{
+ if(g_async_event_handler != 0)
+ {
+ g_async_event_handler(cmd_opcode);
+ }
+}
+
diff --git a/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.h b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.h
new file mode 100644
index 0000000000..96d3af5518
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk.h
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 COMBLK access functions.
+ *
+ * SVN $Revision: 8345 $
+ * SVN $Date: 2016-03-23 11:53:04 +0530 (Wed, 23 Mar 2016) $
+ */
+#ifndef __MSS_COMBLK_H_
+#define __MSS_COMBLK_H_ 1
+
+#include "../../CMSIS/m2sxxx.h"
+#include "mss_comblk_page_handler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ *
+ */
+typedef void(*comblk_completion_handler_t)(uint8_t * p_response, uint16_t response_size);
+
+typedef void (*comblk_async_event_handler_t)(uint8_t event_opcode);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void MSS_COMBLK_init
+(
+ comblk_async_event_handler_t async_event_handler,
+ uint8_t* p_response
+);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void MSS_COMBLK_send_cmd_with_ptr
+(
+ uint8_t cmd_opcode,
+ uint32_t cmd_params_ptr,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_completion_handler_t completion_handler
+);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void MSS_COMBLK_send_cmd
+(
+ const uint8_t * p_cmd,
+ uint16_t cmd_size,
+ const uint8_t * p_data,
+ uint32_t data_size,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_completion_handler_t completion_handler
+);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void MSS_COMBLK_read
+(
+ const uint8_t * p_data,
+ uint16_t cmd_size,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_completion_handler_t completion_handler
+);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void MSS_COMBLK_send_paged_cmd
+(
+ const uint8_t * p_cmd,
+ uint16_t cmd_size,
+ uint8_t * p_response,
+ uint16_t response_size,
+ comblk_page_handler_t page_read_handler,
+ comblk_completion_handler_t completion_handler
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MSS_COMBLK_H_ */
diff --git a/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk_page_handler.h b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk_page_handler.h
new file mode 100644
index 0000000000..1c363df54e
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_sys_services/mss_comblk_page_handler.h
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 MSS COM block driver, page handler callback function prototype.
+ *
+ * SVN $Revision: 8345 $
+ * SVN $Date: 2016-03-23 11:53:04 +0530 (Wed, 23 Mar 2016) $
+ */
+
+#ifndef __MSS_COMBLK_PAGE_HANDLER_H_
+#define __MSS_COMBLK_PAGE_HANDLER_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The comblk_page_handler_t typedef specifies the function prototype of a COMBLK
+ page handler callback function. This callback is used by the system services
+ and COMBLK drivers as part of in-system programming (ISP) to retrieve the next
+ page of programming information to send to the SmartFusion2 System Controller
+ via the COMBLK.
+ The COMBLK page handler must be implemented by the application layer to return
+ the address of the next page of programming data to be sent to the
+ SmartFusion2 system controller. It must return the number of bytes contained
+ in the next page. Returning a value of zero indicates that all programming
+ data has been passed to the system services/COMBLK drivers.
+
+ @code
+ #define PAGE_LENGTH 512
+
+ uint8_t programming_data[PROG_DATA_LENGTH];
+ uint32_t prog_data_index = 0;
+
+ uint32_t page_read_handler
+ (
+ uint8_t const ** pp_next_page
+ )
+ {
+ uint32_t returned_page_length;
+ uint32_t remaining_length;
+
+ *pp_next_page = &programming_data[prog_data_index];
+ remaining_length = PROG_DATA_LENGTH - prog_data_index
+ if(remaining_length > PAGE_LENGTH)
+ {
+ returned_page_length = PAGE_LENGTH;
+ }
+ else
+ {
+ returned_page_length = remaining_length;
+ prog_data_index = PROG_DATA_LENGTH;
+ }
+
+ return returned_page_length;
+ }
+
+ @endcode
+ */
+typedef uint32_t (*comblk_page_handler_t)(uint8_t const ** pp_next_page);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MSS_COMBLK_PAGE_HANDLER_H_ */
diff --git a/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.c b/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.c
new file mode 100644
index 0000000000..982b9d088b
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.c
@@ -0,0 +1,2452 @@
+/*******************************************************************************
+ * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 system services.
+ *
+ * SVN $Revision: 8688 $
+ * SVN $Date: 2016-11-27 17:46:49 +0530 (Sun, 27 Nov 2016) $
+ */
+#include "mss_sys_services.h"
+#include "mss_comblk.h"
+#include "../../CMSIS/mss_assert.h"
+#include <string.h>
+
+/*==============================================================================
+ *
+ */
+/*
+ * Service request command opcodes:
+ */
+#define DEVICE_CERTIFICATE_REQUEST_CMD 0u
+#define SERIAL_NUMBER_REQUEST_CMD 1u
+#define FLASH_FREEZE_REQUEST_CMD 2u
+#define AES128_REQUEST_CMD 3u
+#define USERCODE_REQUEST_CMD 4u
+#define DESIGNVER_REQUEST_CMD 5u
+#define AES256_REQUEST_CMD 6u
+#define KEYTREE_REQUEST_CMD 9u
+#define SHA256_REQUEST_CMD 10u
+#define HMAC_REQUEST_CMD 12u
+#define PPUF_CHALLENGE_RESP_REQUEST_CMD 14u
+#define POINT_MULTIPLICATION_REQUEST_CMD 16u
+#define POINT_ADDITION_REQUEST_CMD 17u
+#define IAP_PROGRAMMING_REQUEST_CMD 20u
+#define ISP_PROGRAMMING_REQUEST_CMD 21u
+#define DIGEST_CHECK_REQUEST_CMD 23u
+#define PUF_ACTIVATION_CODE_REQUEST_CMD 25u
+#define PUF_USER_KEY_CODE_REQUEST_CMD 26u
+#define PUF_FETCH_KEY_REQUEST_CMD 27u
+#define PUF_ECC_PUBLIC_KEY_REQUEST_CMD 28u
+#define PUF_SEED_REQUEST_CMD 29u
+#define SECONDARY_DEVICE_CERTIFICATE_REQUEST_CMD 30u
+#define TAMPER_CONTROL_REQUEST_CMD 31u
+#define NRBG_SELF_TEST_REQUEST_CMD 40u
+#define NRBG_INSTANTIATE_REQUEST_CMD 41u
+#define NRBG_GENERATE_REQUEST_CMD 42u
+#define NRBG_RESEED_REQUEST_CMD 43u
+#define NRBG_UNINSTANTIATE_REQUEST_CMD 44u
+#define NRBG_RESET_REQUEST_CMD 45u
+#define FLASHFREEZE_SHUTDOWN_CMD 224u
+#define ZEROIZATION_REQUEST_CMD 240u
+#define POWER_ON_RESET_DIGEST_ERROR_CMD 241u
+
+/*
+ * System Services requests length:
+ */
+#define FLASH_FREEZE_REQUEST_LENGTH 2u
+
+/*
+ * Service response lengths:
+ */
+#define STANDARD_SERV_RESP_LENGTH 6u
+#define SERIAL_NUMBER_SERV_RESP_LENGTH 6u
+#define USERCODE_SERV_RESP_LENGTH 6u
+#define DESIGNVER_SERV_RESP_LENGTH 6u
+#define DEVICE_CERT_SERV_RESP_LENGTH 6u
+#define SECONDARY_DEVICE_CERT_SERV_RESP_LENGTH 6u
+#define ISP_PROG_SERV_RESP_LENGTH 2u
+#define IAP_PROG_SERV_RESP_LENGTH 2u
+#define NRBG_RESET_SERV_RESP_LENGTH 2u
+#define NRBG_SELF_TEST_SERV_RESP_LENGTH 2u
+#define NRBG_UNINST_SERV_RESP_LENGTH 3u
+#define DRBG_RESET_SERV_RESP_LENGTH 2u
+#define DIGEST_CHECK_SERV_RESP_LENGTH 2u
+#define FLASH_FREEZE_SERV_RESP_LENGTH 2u
+#define PORDIGEST_CHECK_SERV_RESP_LENGTH 2u
+#define TAMPER_CONTROL_SERV_RESP_LENGTH 2u
+#define PUF_USER_ACTIVATION_CODE_RESP_LENGTH 2u
+#define PUF_GET_NUMBER_OF_KEYS_RESP_LENGTH 6u
+#define PUF_ENROLL_KEYS_RESP_LENGTH 6u
+#define PUF_EXPORT_ALL_KEYCODES_RESP_LENGTH 6u
+#define PUF_IMPORT_ALL_KEYCODES_RESP_LENGTH 6u
+#define FACC_STANDBY_SEL 0u
+#define MSS_25_50MHZ_EN 1u
+#define MSS_1MHZ_EN 1u
+#define FACC_STANDBY_SHIFT 6u
+#define MSS_25_50MHZ_EN_SHIFT 9u
+#define MSS_1MHZ_EN_SHIFT 10u
+#define FACC_STANDBY_SEL_MASK 0x000001C0u
+#define MSS_25_50MHZ_EN_MASK 0x00000200u
+#define MSS_1MHZ_EN_MASK 0x00000400u
+
+/*
+ * Non Deterministic Random Bit Generator defines:
+ */
+#define INVALID_NRBG_HANDLE 0xFFu
+
+/*
+ * RTC_WAKEUP_CR system register bit masks:
+ */
+#define RTC_WAKEUP_G4C_EN_MASK 0x00000004u
+#define RTC_WAKEUP_FAB_EN_MASK 0x00000002u
+
+/*
+ * PUF user activation code sub command
+ */
+#define PUF_CREATE_USER_ACTIVATION_CODE 0u
+#define PUF_DELETE_USER_ACTIVATION_CODE 1u
+
+/*
+ * Sub Command for PUF service
+ */
+#define PUF_GET_NUMBER_OF_KC_SUBCOMMAND 0u
+#define PUF_CREATE_EXT_KC_SUBCOMMAND 1u
+#define PUF_CREATE_INT_KC_SUBCOMMAND 2u
+#define PUF_EXPORT_ALL_KC_SUBCOMMAND 3u
+#define PUF_IMPORT_ALL_KC_SUBCOMMAND 4u
+#define PUF_DELETE_KC_SUBCOMMAND 5u
+
+/*==============================================================================
+ * Local functions.
+ */
+static void request_completion_handler(uint8_t * p_response, uint16_t response_size);
+static void signal_request_start(void);
+static uint16_t wait_for_request_completion(void);
+static uint8_t execute_service
+(
+ uint8_t cmd_opcode,
+ uint8_t * cmd_params_ptr,
+ uint8_t * response,
+ uint16_t response_length
+);
+
+static void asynchronous_event_handler(uint8_t event_opcode);
+
+static void write_ptr_value_into_array
+(
+ const uint8_t * pointer,
+ uint8_t target_array[],
+ uint32_t array_index
+);
+
+static void write_array_into_ptr_value
+(
+ uint8_t** pointer,
+ uint8_t target_array[],
+ uint32_t array_index
+);
+static void revert_clk_config(void);
+static uint8_t clk_switching_fix(void);
+static uint8_t* determine_seq(uint8_t val, uint8_t* len);
+
+/*==============================================================================
+ * Global variables
+ */
+static volatile uint8_t g_request_in_progress = 0u;
+static volatile uint16_t g_last_response_length = 0u;
+static sys_serv_async_event_handler_t g_event_handler = 0;
+static uint8_t g_response[PORDIGEST_CHECK_SERV_RESP_LENGTH] = {0u};
+static uint32_t g_initial_mssddr_facc1_cr = 0U;
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+void MSS_SYS_init(sys_serv_async_event_handler_t event_handler)
+{
+ g_event_handler = event_handler;
+ g_last_response_length = 0u;
+ g_request_in_progress = 0u;
+
+ /*
+ * Set a default good value for g_initial_mssddr_facc1_cr used to control
+ * the clock dividers coming in and out of Flash*Freeze.
+ */
+ g_initial_mssddr_facc1_cr = SYSREG->MSSDDR_FACC1_CR;
+
+ /*
+ * Initialize the COMBLK used to communicate with the System Controller.
+ */
+ MSS_COMBLK_init(asynchronous_event_handler, g_response);
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+/* Tamper attempt/failure range */
+#define TAMPER_ATTEMPT_DETECT_OPCODE_RANGE_MIN 0x80u
+#define TAMPER_ATTEMPT_DETECT_OPCODE_RANGE_MAX 0x8Fu
+#define TAMPER_FAILURE_DETECT_OPCODE_RANGE_MIN 0x90u
+#define TAMPER_FAILURE_DETECT_OPCODE_RANGE_MAX 0x9Fu
+#define TAMPER_CLOCK_MONITOR_ERROR_OPCODE 0xA0u
+#define TAMPER_HARDWARE_MONITOR_ERROR_OPCODE_RANGE_MIN 0xB1u
+#define TAMPER_HARDWARE_MONITOR_ERROR_OPCODE_RANGE_MAX 0xB7u
+
+#define FACC_GLMUX_SEL_MASK 0x00001000u
+#define DELAY_MORE_THAN_10US 5000U
+static void asynchronous_event_handler(uint8_t event_opcode)
+{
+ if (event_opcode == FLASH_FREEZE_SHUTDOWN_OPCODE)
+ {
+ uint32_t running_on_standby_clock;
+ volatile uint32_t timeout;
+
+ /*
+ * Wait for the System Controller to switch the system's clock
+ * from the main clock to the standby clock. This should take place
+ * within 10us of receiving the shut-down event.
+ */
+ timeout = DELAY_MORE_THAN_10US;
+ do
+ {
+ running_on_standby_clock = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;
+ --timeout;
+ }
+ while ((running_on_standby_clock == 0U) && (timeout != 0U));
+
+ /* Call the user's event handler. */
+ if(g_event_handler != 0)
+ {
+ g_event_handler(event_opcode, g_response[1]);
+ }
+ }
+ else if (event_opcode == FLASH_FREEZE_EXIT_OPCODE)
+ {
+ uint32_t running_on_standby_clock;
+ volatile uint32_t timeout;
+
+ /*
+ * Wait for the System Controller to switch the system's clock
+ * from the standby clock to the main clock. This should take place
+ * within 10us of receiving the shut-down event.
+ */
+ timeout = DELAY_MORE_THAN_10US;
+ do
+ {
+ running_on_standby_clock = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;
+ --timeout;
+ }
+ while ((running_on_standby_clock != 0U) && (timeout != 0U));
+
+ /* Restore the clock dividers values of FACC1 register. */
+ revert_clk_config();
+
+ if(g_event_handler != 0)
+ {
+ /* Call the user's event handler. */
+ g_event_handler(event_opcode, g_response[1]);
+ }
+ }
+ else
+ {
+ if ((event_opcode == POR_DIGEST_ERROR_OPCODE) || \
+ ((event_opcode >= TAMPER_ATTEMPT_DETECT_OPCODE_RANGE_MIN) && \
+ (event_opcode <= TAMPER_FAILURE_DETECT_OPCODE_RANGE_MAX)) || \
+ (event_opcode == TAMPER_CLOCK_MONITOR_ERROR_OPCODE) || \
+ ((event_opcode >= TAMPER_HARDWARE_MONITOR_ERROR_OPCODE_RANGE_MIN) && \
+ (event_opcode <= TAMPER_HARDWARE_MONITOR_ERROR_OPCODE_RANGE_MAX)))
+ {
+ /*
+ * Inform to the application that new asynchronous message is received,
+ * only if application call-back function is registered during
+ * initialization.
+ */
+ if(g_event_handler != 0)
+ {
+ /* Call the user's event handler. */
+ g_event_handler(event_opcode, g_response[1]);
+ }
+ }
+ }
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_get_serial_number
+(
+ uint8_t * p_serial_number
+)
+{
+ uint8_t response[SERIAL_NUMBER_SERV_RESP_LENGTH];
+ uint8_t status;
+
+ status = execute_service(SERIAL_NUMBER_REQUEST_CMD,
+ p_serial_number,
+ response,
+ SERIAL_NUMBER_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_get_user_code
+(
+ uint8_t * p_user_code
+)
+{
+ uint8_t response[USERCODE_SERV_RESP_LENGTH];
+ uint8_t status;
+
+ status = execute_service(USERCODE_REQUEST_CMD,
+ p_user_code,
+ response,
+ USERCODE_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_get_design_version
+(
+ uint8_t * p_design_version
+)
+{
+ uint8_t response[DESIGNVER_SERV_RESP_LENGTH];
+ uint8_t status;
+
+ status = execute_service(DESIGNVER_REQUEST_CMD,
+ p_design_version,
+ response,
+ DESIGNVER_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_get_device_certificate
+(
+ uint8_t * p_device_certificate
+)
+{
+ uint8_t response[DEVICE_CERT_SERV_RESP_LENGTH];
+ uint8_t status;
+
+ status = execute_service(DEVICE_CERTIFICATE_REQUEST_CMD,
+ p_device_certificate,
+ response,
+ DEVICE_CERT_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_get_secondary_device_certificate
+(
+ uint8_t * p_secondary_device_certificate
+)
+{
+ uint8_t response[SECONDARY_DEVICE_CERT_SERV_RESP_LENGTH];
+ uint8_t status;
+
+ /*
+ * The get secondary device certificate system service is not available on
+ * M2S050 rev A, rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ status = execute_service(SECONDARY_DEVICE_CERTIFICATE_REQUEST_CMD,
+ p_secondary_device_certificate,
+ response,
+ SECONDARY_DEVICE_CERT_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+#define CONFIG_CLOCK_DIV_MASK 0xFFC7F103u
+#define CONFIG_CLOCK_DIV_32_RATIO 0x00301CD8u
+
+/* Sequence array for divisor */
+uint8_t div1_seq[]={ 0x00, 0x01, 0x05, 0x07};
+uint8_t div2_seq[]={ 0x01, 0x05, 0x07};
+uint8_t div4_seq[]={ 0x02, 0x03, 0x01, 0x05, 0x07};
+uint8_t div8_seq[]={ 0x04, 0x06, 0x07};
+uint8_t div16_seq[]={ 0x05, 0x07};
+uint8_t div32_seq[]={ 0x06, 0x07 };
+
+/* Divisor array is used to store the values of APB0_DIVISOR, APB1_DIVISOR,
+ * M3_CLK_DIVISOR and FIC64_DIVISOR bit-fields before entering flash freeze.
+ * This value will be used to revert back the value of FACC1 register after
+ * exiting from Flash Freeze/IAP/Fabric digest check.
+ */
+uint32_t divisor[4] = {0x00};
+volatile uint8_t ind = 0;
+
+static uint8_t* determine_seq(uint8_t val, uint8_t* len)
+{
+ uint8_t*seq;
+
+ switch(val)
+ {
+ case 0:
+ seq = &div1_seq[0];
+ *len = 4;
+ break;
+
+ case 1:
+ seq = &div2_seq[0];
+ *len = 3;
+ break;
+
+ case 2:
+ seq = &div4_seq[0];
+ *len = 5;
+ break;
+
+ case 4:
+ seq = &div8_seq[0];
+ *len = 3;
+ break;
+
+ case 5:
+ seq = &div16_seq[0];
+ *len = 2;
+ break;
+
+ case 6:
+ seq = &div32_seq[0];
+ *len = 2;
+ break;
+
+ default:
+ *len = 0;
+ seq = NULL;
+ break;
+ }
+
+ return seq;
+}
+
+#define CLOCK_SWITCHING_SUCCESS 0x00u
+#define CLOCK_SWITCHING_ERROR 0x01u
+
+/* SAR 80563 - Workaround for Glitchless Clock Multiplexer Switching Issue
+ * If user has requested for fabric digest check/IAP/Flash Freeze service, then
+ * the firmware will change the clock divisor values of FACC1 register based on
+ * device version to avoid Glitchless Clock Multiplexer Switching Issue.
+ * If the device is 010/025/050/090/150 device, Cortex-M3 firmware
+ * dynamically divides down fclk, pclk0, pclk1 and clk_fic64 to the divided
+ * by 32 versions. If the device is 05 device, firmware will load the
+ * divisor values in sequenced from the start setting to the divide by 32
+ * setting. If the device is 060 device, then firmware will compare the
+ * divisor values of fclk, pclk0, pclk1 and clk_fic64, and if the divisor
+ * values are equal to each other, then firmware will send requested command to
+ * system controller otherwise return CLOCK_SWITCHING_ERROR error.
+ */
+static uint8_t clk_switching_fix(void)
+{
+ uint8_t* sequence;
+ uint8_t len;
+ volatile uint32_t g_mssddr_facc1_cr = SYSREG->MSSDDR_FACC1_CR;
+ uint32_t var = 0;
+ uint32_t temp = 0;
+ uint32_t device_version;
+ uint8_t status = CLOCK_SWITCHING_SUCCESS;
+
+ device_version = (SYSREG->DEVICE_VERSION & 0xFFFFu);
+
+ /* For 10/25/50/90/150 devices */
+ if((0xF802u == device_version) || \
+ (0xF803u == device_version) || \
+ (0xF804u == device_version)|| \
+ (0xF807u == device_version) || \
+ (0xF806u == device_version))
+ {
+ /* Dynamically divides down fclk, pclk0, pclk1 and clk_fic64
+ * to the divided by 32 versions and M3_CLK, PCLK0, PCLK1,
+ * CLK_FIC64 all driven from CLK_STANDBY clock.
+ */
+ SYSREG->MSSDDR_FACC1_CR = (SYSREG->MSSDDR_FACC1_CR & CONFIG_CLOCK_DIV_MASK) | \
+ CONFIG_CLOCK_DIV_32_RATIO;
+ status = CLOCK_SWITCHING_SUCCESS;
+ }
+
+ /* For 05 devices
+ * When modifying clock divisor settings on M2S005, it is necessary to
+ * sequence them, depending on the starting configuration.
+ */
+ else if(0xF805u == device_version)
+ {
+ /* For APB0_DIVISOR setting */
+ divisor[0] = ((g_mssddr_facc1_cr >> 2) & 0x00000007);
+ sequence = determine_seq(divisor[0], &len);
+
+ for(var = 1; var < len; var++)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFFFE3u;
+ temp |= ((uint32_t)(sequence[var]) << 2);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For APB1_DIVISOR setting */
+ divisor[1] = ((g_mssddr_facc1_cr >> 5) & 0x00000007);
+ sequence = determine_seq(divisor[1], &len);
+
+ for(var = 1; var < len; var++)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFFF1Fu;
+ temp |= ((uint32_t)(sequence[var]) << 5);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For M3_CLK_DIVISOR setting */
+ divisor[2] = ((g_mssddr_facc1_cr >> 9) & 0x00000007);
+ sequence = determine_seq(divisor[2], &len);
+
+ for(var = 1; var < len; var++)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFF1FFu;
+ temp |= ((uint32_t)(sequence[var]) << 9);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For FIC64_DIVISOR setting */
+ divisor[3] = ((g_mssddr_facc1_cr >> 19) & 0x00000007);
+ sequence = determine_seq(divisor[3], &len);
+ for(var = 1; var < len; var++)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFC7FFFFu;
+ temp |= ((uint32_t)(sequence[var]) << 19);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* Set the value of FACC_GLMUX_SEL bitfield of FACC1 register to 1 so
+ * that M3_CLK, PCLK0, PCLK1, CLK_FIC64 all driven from CLK_STANDBY
+ * clock.
+ */
+ SYSREG->MSSDDR_FACC1_CR = SYSREG->MSSDDR_FACC1_CR | 0x00001000u;
+
+ status = CLOCK_SWITCHING_SUCCESS;
+ }
+ /* For 060 devices */
+ else if(0xF808u == device_version)
+ {
+ /* The divisor setting should be such that all the divisor should be
+ * equal to each other and set to divide by 1,2,4,8, and 16 (but not 32)
+ */
+ divisor[0] = ((g_mssddr_facc1_cr >> 2) & 0x00000007);
+ divisor[1] = ((g_mssddr_facc1_cr >> 5) & 0x00000007);
+ divisor[2] = ((g_mssddr_facc1_cr >> 9) & 0x00000007);
+ divisor[3] = ((g_mssddr_facc1_cr >> 19) & 0x00000007);
+
+ for(var = 1; var < 4; var++)
+ {
+ if((divisor[var] != divisor[0]) || \
+ (divisor[0] > 5) || (divisor[var] > 5))
+ {
+ /* If the divisor value does meet the criteria, log the clock
+ * switching error.
+ */
+ status = CLOCK_SWITCHING_ERROR;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* Do Nothing. */
+ }
+
+ return status;
+}
+
+/* SAR 80563 - Workaround for Glitchless Clock Multiplexer Switching Issue
+ * Revert back original values of various divisor in FACC1 register after
+ * completing the fabric digest check/IAP/Flash Freeze service.
+ */
+static void revert_clk_config(void)
+{
+ uint8_t* sequence;
+ uint8_t len;
+ uint8_t var = 0;
+ uint32_t temp = 0;
+ uint32_t device_version;
+
+ device_version = (SYSREG->DEVICE_VERSION & 0xFFFFu);
+
+ /* Revert back values for 10/25/50/90/150 devices */
+ if((0xF802u == device_version) || (0xF803u == device_version) || \
+ (0xF804u == device_version)||(0xF807u == device_version) || \
+ (0xF806u == device_version))
+ {
+ /* Restore the MSS clock dividers to their normal operations value. */
+ SYSREG->MSSDDR_FACC1_CR = g_initial_mssddr_facc1_cr;
+ }
+
+ /* Revert back values for 05 devices in reverse sequence. */
+ else if(0xF805u == device_version)
+ {
+ sequence = determine_seq(divisor[0], &len);
+ for(var = len; var > 0; var--)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFFFE3u;
+ temp |= ((uint32_t)(sequence[var - 1]) << 2);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For APB1_DIVISOR setting */
+ sequence = determine_seq(divisor[1], &len);
+ for(var = len; var > 0; var--)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFFF1Fu;
+ temp |= ((uint32_t)(sequence[var - 1]) << 5);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For M3_CLK_DIVISOR setting */
+ sequence = determine_seq(divisor[2], &len);
+ for(var = len; var > 0; var--)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFFFF1FFu;
+ temp |= ((uint32_t)(sequence[var - 1]) << 9);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* For FIC64_DIVISOR setting */
+ sequence = determine_seq(divisor[3], &len);
+ for(var = len; var > 0; var--)
+ {
+ temp = SYSREG->MSSDDR_FACC1_CR;
+ temp &= 0xFFC7FFFFu;
+ temp |= ((uint32_t)(sequence[var - 1]) << 19);
+ SYSREG->MSSDDR_FACC1_CR = temp;
+ }
+
+ /* Set the value of FACC_GLMUX_SEL bitfield of FACC1 register to 0 so
+ * that M3_CLK, PCLK0, PCLK1, CLK_FIC64 all driven from stage 2
+ * dividers (from CLK_SRC).
+ */
+ SYSREG->MSSDDR_FACC1_CR = SYSREG->MSSDDR_FACC1_CR & 0xFFFFEFFFu;
+ }
+ else
+ {
+ /* Do Nothing. */
+ }
+}
+
+uint8_t MSS_SYS_flash_freeze(uint8_t options)
+{
+ uint8_t status;
+ uint8_t clk_switch_status = CLOCK_SWITCHING_SUCCESS;
+ uint16_t actual_response_length;
+ uint8_t flash_freeze_req[FLASH_FREEZE_REQUEST_LENGTH];
+ uint8_t response[FLASH_FREEZE_SERV_RESP_LENGTH];
+
+ /*
+ * The Flash Freeze system service is not available on M2S050 rev A and rev B.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+
+ /*
+ * Keep track of the clocks configuration before entering Flash*Freeze so
+ * that it can be restored on Flash*Freeze exit.
+ */
+ g_initial_mssddr_facc1_cr = SYSREG->MSSDDR_FACC1_CR;
+
+ /* SAR 80563
+ * Cortex-M3 firmware dynamically divides down fclk, pclk0, pclk1 and
+ * clk_fic64 to the divided by 32 versions based on device version.
+ */
+ clk_switch_status = clk_switching_fix();
+
+ if(clk_switch_status == CLOCK_SWITCHING_SUCCESS)
+ {
+ /*
+ * Enable RTC wake-up interrupt to System Controller and FPGA fabric.
+ */
+ SYSREG->RTC_WAKEUP_CR |= (RTC_WAKEUP_G4C_EN_MASK | RTC_WAKEUP_FAB_EN_MASK);
+
+ signal_request_start();
+
+ flash_freeze_req[0] = FLASH_FREEZE_REQUEST_CMD;
+ flash_freeze_req[1] = options;
+
+ MSS_COMBLK_send_cmd(flash_freeze_req, /* p_cmd */
+ FLASH_FREEZE_REQUEST_LENGTH, /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ FLASH_FREEZE_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((FLASH_FREEZE_SERV_RESP_LENGTH == actual_response_length) &&
+ (FLASH_FREEZE_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+ }
+ else
+ {
+ /* SAR 80563
+ * CLK Divisor error occurs on 060 device. The user should make sure
+ * that the all divisor i.e fclk, pclk0, pclk1 and clk_fic64 divisor
+ * must be equal to each other and set to to divide by 1,2, 4, 8, 16(but
+ * not 32). If the divisor value does not meet the above criteria, the
+ * function will not send Flash Freeze command to system controller and
+ * will return CLK divisor error.
+ */
+ status = MSS_SYS_CLK_DIVISOR_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+#define AES128_KEY_LENGTH 16u
+#define IV_LENGTH 16u
+
+#define AES256_KEY_LENGTH 32u
+
+#define HMAC_KEY_LENGTH 32u
+
+uint8_t MSS_SYS_128bit_aes
+(
+ const uint8_t * key,
+ const uint8_t * iv,
+ uint16_t nb_blocks,
+ uint8_t mode,
+ uint8_t * dest_addr,
+ const uint8_t * src_addr)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[44];
+ uint8_t status;
+
+ memcpy(&params[0], key, AES128_KEY_LENGTH);
+ memcpy(&params[16], iv, IV_LENGTH);
+
+ params[32] = (uint8_t)nb_blocks;
+ params[33] = (uint8_t)(nb_blocks >> 8u);
+ params[34] = mode;
+ params[35] = 0u;
+
+ write_ptr_value_into_array(dest_addr, params, 36u);
+ write_ptr_value_into_array(src_addr, params, 40u);
+
+ status = execute_service(AES128_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_256bit_aes
+(
+ const uint8_t * key,
+ const uint8_t * iv,
+ uint16_t nb_blocks,
+ uint8_t mode,
+ uint8_t * dest_addr,
+ const uint8_t * src_addr
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[60];
+ uint8_t status;
+
+ memcpy(&params[0], key, AES256_KEY_LENGTH);
+ memcpy(&params[32], iv, IV_LENGTH);
+
+ params[48] = (uint8_t)nb_blocks;
+ params[49] = (uint8_t)(nb_blocks >> 8u);
+ params[50] = mode;
+ params[51] = 0u;
+
+ write_ptr_value_into_array(dest_addr, params, 52u);
+ write_ptr_value_into_array(src_addr, params, 56u);
+
+ status = execute_service(AES256_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_sha256
+(
+ const uint8_t * p_data_in,
+ uint32_t length,
+ uint8_t * result
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[12];
+ uint8_t status;
+
+ params[0] = (uint8_t)((uint32_t)length);
+ params[1] = (uint8_t)((uint32_t)length >> 8u);
+ params[2] = (uint8_t)((uint32_t)length >> 16u);
+ params[3] = (uint8_t)((uint32_t)length >> 24u);
+
+ write_ptr_value_into_array(result, params, 4u);
+ write_ptr_value_into_array(p_data_in, params, 8u);
+
+ status = execute_service(SHA256_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_hmac
+(
+ const uint8_t * key,
+ const uint8_t * p_data_in,
+ uint32_t length,
+ uint8_t * p_result
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[58];
+ uint8_t status;
+
+ memcpy(&params[0], key, HMAC_KEY_LENGTH);
+
+ params[32] = (uint8_t)((uint32_t)length);
+ params[33] = (uint8_t)((uint32_t)length >> 8u);
+ params[34] = (uint8_t)((uint32_t)length >> 16u);
+ params[35] = (uint8_t)((uint32_t)length >> 24u);
+
+ write_ptr_value_into_array(p_data_in, params, 36u);
+ write_ptr_value_into_array(p_result, params, 40u);
+
+ status = execute_service(HMAC_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+#define KEYTREE_KEY_LENGTH 32
+#define KEYTREE_PATH_LENGTH 16
+
+uint8_t MSS_SYS_key_tree
+(
+ uint8_t* p_key,
+ uint8_t op_type,
+ const uint8_t* path
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[49];
+ uint8_t status;
+
+ memcpy(&params[0], p_key, KEYTREE_KEY_LENGTH);
+
+ params[32] = op_type;
+
+ memcpy(&params[33], path, KEYTREE_PATH_LENGTH);
+
+ status = execute_service(KEYTREE_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ if(status == MSS_SYS_SUCCESS)
+ {
+ memcpy(p_key, &params[0], KEYTREE_KEY_LENGTH);
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_challenge_response
+(
+ uint8_t* p_key,
+ uint8_t op_type,
+ const uint8_t* path
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[21];
+ uint8_t status;
+
+ params[0] = (uint8_t)((uint32_t)p_key);
+ params[1] = (uint8_t)((uint32_t)p_key >> 8u);
+ params[2] = (uint8_t)((uint32_t)p_key >> 16u);
+ params[3] = (uint8_t)((uint32_t)p_key >> 24u);
+
+ params[4] = op_type;
+
+ memcpy(&params[5], path, KEYTREE_PATH_LENGTH);
+
+ status = execute_service(PPUF_CHALLENGE_RESP_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_reset(void)
+{
+ uint8_t status;
+ uint16_t actual_response_length;
+ uint8_t reset_cmd[4];
+ uint8_t response[NRBG_RESET_SERV_RESP_LENGTH];
+
+ signal_request_start();
+
+ reset_cmd[0] = NRBG_RESET_REQUEST_CMD;
+ reset_cmd[1] = 0u;
+ reset_cmd[2] = 0u;
+ reset_cmd[3] = 0u;
+
+ MSS_COMBLK_send_cmd(reset_cmd, /* p_cmd */
+ sizeof(reset_cmd), /* cmd_size */
+ 0, /* p_data */
+ 0, /* data_size */
+ response, /* p_response */
+ DRBG_RESET_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((NRBG_RESET_SERV_RESP_LENGTH == actual_response_length) &&
+ (NRBG_RESET_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_self_test(void)
+{
+ uint8_t status;
+ uint16_t actual_response_length;
+ uint8_t self_test;
+ uint8_t response[NRBG_SELF_TEST_SERV_RESP_LENGTH];
+
+ signal_request_start();
+
+ self_test = NRBG_SELF_TEST_REQUEST_CMD;
+
+ MSS_COMBLK_send_cmd(&self_test, /* p_cmd */
+ sizeof(self_test), /* cmd_size */
+ 0, /* p_data */
+ 0, /* data_size */
+ response, /* p_response */
+ NRBG_SELF_TEST_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((NRBG_SELF_TEST_SERV_RESP_LENGTH == actual_response_length) &&
+ (NRBG_SELF_TEST_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_instantiate
+(
+ const uint8_t * personalization_str,
+ uint16_t personalization_str_length,
+ uint8_t * p_nrbg_handle
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t instantiate_params[7];
+ uint8_t status;
+
+ write_ptr_value_into_array(personalization_str, instantiate_params, 0u);
+
+ instantiate_params[4] = (uint8_t)personalization_str_length;
+ instantiate_params[5] = (uint8_t)(personalization_str_length >> 8u);
+ instantiate_params[6] = INVALID_NRBG_HANDLE;
+
+ status = execute_service(NRBG_INSTANTIATE_REQUEST_CMD,
+ instantiate_params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ if(MSS_SYS_SUCCESS == status)
+ {
+ *p_nrbg_handle = instantiate_params[6];
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_generate
+(
+ const uint8_t * p_requested_data,
+ const uint8_t * p_additional_input,
+ uint8_t requested_length,
+ uint8_t additional_input_length,
+ uint8_t pr_req,
+ uint8_t nrbg_handle
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t generate_params[12];
+ uint8_t status;
+
+ write_ptr_value_into_array(p_requested_data, generate_params, 0u);
+ write_ptr_value_into_array(p_additional_input, generate_params, 4u);
+
+ generate_params[8] = requested_length;
+ generate_params[9] = additional_input_length;
+ generate_params[10] = pr_req;
+ generate_params[11] = nrbg_handle;
+
+ status = execute_service(NRBG_GENERATE_REQUEST_CMD,
+ generate_params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_reseed
+(
+ const uint8_t * p_additional_input,
+ uint8_t additional_input_length,
+ uint8_t nrbg_handle
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[6];
+ uint8_t status;
+
+ write_ptr_value_into_array(p_additional_input, params, 0u);
+
+ params[4] = (uint8_t)additional_input_length;
+ params[5] = nrbg_handle;
+
+ status = execute_service(NRBG_RESEED_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_nrbg_uninstantiate
+(
+ uint8_t nrbg_handle
+)
+{
+ uint8_t status;
+ uint16_t actual_response_length;
+ uint8_t uninstantiate_req[2];
+ uint8_t response[NRBG_UNINST_SERV_RESP_LENGTH];
+
+ signal_request_start();
+
+ uninstantiate_req[0] = NRBG_UNINSTANTIATE_REQUEST_CMD;
+ uninstantiate_req[1] = nrbg_handle;
+
+ MSS_COMBLK_send_cmd(uninstantiate_req, /* p_cmd */
+ sizeof(uninstantiate_req), /* cmd_size */
+ 0, /* p_data */
+ 0, /* data_size */
+ response, /* p_response */
+ NRBG_UNINST_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((NRBG_UNINST_SERV_RESP_LENGTH == actual_response_length) &&
+ (NRBG_UNINSTANTIATE_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+void MSS_SYS_zeroize_device(void)
+{
+ /*
+ * We only need to send one command byte to initiate zeroization.
+ * The zeroization process should result in the Cortex-M3 being reset. This
+ * means we should never reach the end of this function if zeroization is
+ * actually performed.
+ */
+ uint8_t zeroization_req = ZEROIZATION_REQUEST_CMD;
+
+ /*
+ * The Zeroization system service is not available on M2S050 rev A, rev B
+ * and rev C.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ MSS_COMBLK_send_cmd(&zeroization_req, /* p_cmd */
+ sizeof(zeroization_req), /* cmd_size */
+ 0, /* p_data */
+ 0, /* data_size */
+ 0, /* p_response */
+ 0, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ /* SAR 74647
+ * Zeroization is only performed if the user has instantiated the tamper
+ * macro (from the Libero Catalog) in the hardware design, configured the
+ * tamper macro to enable zeroization and set the required zeroization
+ * options. If program execution idles here, or in the
+ * wait_for_request_completion() function that follows, you should verify
+ * that zeroization is properly enabled in the hardware design.
+ */
+ ASSERT(g_request_in_progress == 0u);
+
+ /*
+ * Handle case where Zeroization is not enabled in the device in Release
+ * mode.
+ */
+ wait_for_request_completion();
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+#define NVM_FREQRNG_MASK 0x00001FE0U
+#define NVM_FREQRNG_MAX ((uint32_t)0xFFU << 5U)
+
+static uint8_t g_isp_response[ISP_PROG_SERV_RESP_LENGTH];
+sys_serv_isp_complete_handler_t g_isp_completion_handler = 0;
+comblk_page_handler_t g_isp_page_read_handler = 0;
+
+/*
+ * g_initial_envm_cr contains the hardware design's original eNVM configuration
+ * set through the ENVM_CR system register. This global variable is used to
+ * store the eNVM's configuration while the ISP/IAP is executing with an eNVM
+ * configuration ensuring successful eNVM programming on all SamrtFusion2
+ * devices. It is then used to restore the eNVM's configuration once ISP/IAP has
+ * completed. SAR 57545.
+ */
+static uint32_t g_initial_envm_cr = 0x00001FF1U;
+/*
+ * g_initial_mssddr_facc2_cr contains the hardware design's original MSS DDR
+ * Fabric Alignment Clock Controller (FACC) 2 configuration set through the
+ * MSSDDR_FACC2_CR system register. This global variable is used to
+ * store the FACC2's configuration while the ISP/IAP is executing on all
+ * SamrtFusion2 devices. It is then used to restore the Fabric alignment clock
+ * configuration once ISP/IAP has completed.
+ */
+static uint32_t g_initial_mssddr_facc2_cr = 0x00;
+static uint8_t g_mode = 0;
+static uint8_t wait_for_clock_switch = 1;
+
+static uint32_t isp_page_read_handler
+(
+ uint8_t const ** pp_next_page
+)
+{
+ uint32_t remaining_length = 0;
+ uint32_t running_on_standby_clock;
+ volatile uint32_t timeout;
+
+ if((g_mode != MSS_SYS_PROG_AUTHENTICATE) & (wait_for_clock_switch == 1))
+ {
+ timeout = DELAY_MORE_THAN_10US;
+ do
+ {
+ running_on_standby_clock = SYSREG->MSSDDR_FACC1_CR & FACC_GLMUX_SEL_MASK;
+ --timeout;
+ }
+ while ((running_on_standby_clock == 0U) && (timeout != 0U));
+ wait_for_clock_switch = 0;
+ }
+
+ if(g_isp_page_read_handler != 0)
+ {
+ remaining_length = g_isp_page_read_handler(pp_next_page);
+ }
+
+ return remaining_length;
+}
+
+static void isp_sys_completion_handler
+(
+ uint8_t * p_response,
+ uint16_t length
+)
+{
+ if(g_mode != MSS_SYS_PROG_AUTHENTICATE)
+ {
+ /*
+ * Restore the eNVM's frequency range to the values used before ISP was
+ * started.
+ */
+ SYSREG->ENVM_CR = g_initial_envm_cr;
+
+ /*
+ * Restore the MSS DDR FACC 2 configuration to the values used before ISP
+ * was started.
+ */
+ SYSREG->MSSDDR_FACC2_CR = g_initial_mssddr_facc2_cr;
+ }
+
+ if(g_isp_completion_handler != 0)
+ {
+ g_isp_completion_handler(p_response[1]);
+ }
+}
+
+uint8_t MSS_SYS_start_isp
+(
+ uint8_t mode,
+ comblk_page_handler_t page_read_handler,
+ sys_serv_isp_complete_handler_t isp_completion_handler
+)
+{
+ uint8_t isp_prog_request[2];
+ uint8_t clk_switch_status = CLOCK_SWITCHING_SUCCESS;
+ uint8_t status = MSS_SYS_SUCCESS;
+
+ if(mode == MSS_SYS_PROG_VERIFY)
+ {
+ /*
+ * Check fabric digest before performing ISP verify
+ */
+ MSS_SYS_check_digest(MSS_SYS_DIGEST_CHECK_FABRIC);
+ }
+
+ g_mode = mode;
+
+ if(mode != MSS_SYS_PROG_AUTHENTICATE)
+ {
+ /*
+ * Keep a copy of the initial eNVM configuration used before ISP was
+ * initiated. The eNVM configuration will be restored, as part of the ISP
+ * completion handler, when ISP completes.
+ */
+ g_initial_envm_cr = SYSREG->ENVM_CR;
+
+ /* Store the MSS DDR FACC 2 register value so that its can be restored back
+ * when the ISP operation is completed in asynchronous_event_handler. */
+ g_initial_mssddr_facc2_cr = SYSREG->MSSDDR_FACC2_CR;
+
+ /*
+ * Set the eNVM's frequency range to its maximum. This is required to ensure
+ * successful eNVM programming on all devices.
+ */
+ SYSREG->ENVM_CR = (g_initial_envm_cr & ~NVM_FREQRNG_MASK) | NVM_FREQRNG_MAX;
+
+ /* Select output of MUX 0, MUX 1 and MUX 2 during standby */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR & ((uint32_t)(FACC_STANDBY_SEL << FACC_STANDBY_SHIFT) | ~FACC_STANDBY_SEL_MASK);
+
+ /* Enable the signal for the 50 MHz RC oscillator */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR | ((uint32_t)(MSS_25_50MHZ_EN << MSS_25_50MHZ_EN_SHIFT) & MSS_25_50MHZ_EN_MASK);
+
+ /* Enable the signal for the 1 MHz RC oscillator */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR | ((uint32_t)(MSS_1MHZ_EN << MSS_1MHZ_EN_SHIFT) & MSS_1MHZ_EN_MASK);
+
+ /* SAR 80563
+ * Cortex-M3 firmware dynamically divides down fclk, pclk0, pclk1 and
+ * clk_fic64 to the divided by 32 versions based on device version.
+ */
+ clk_switch_status = clk_switching_fix();
+
+ wait_for_clock_switch = 1;
+ }
+
+ if(clk_switch_status == CLOCK_SWITCHING_SUCCESS)
+ {
+ signal_request_start();
+
+ isp_prog_request[0] = ISP_PROGRAMMING_REQUEST_CMD;
+ isp_prog_request[1] = mode;
+
+ g_isp_completion_handler = isp_completion_handler;
+
+ g_isp_page_read_handler = page_read_handler;
+
+ MSS_COMBLK_send_paged_cmd(isp_prog_request, /* p_cmd */
+ sizeof(isp_prog_request), /* cmd_size */
+ g_isp_response, /* p_response */
+ ISP_PROG_SERV_RESP_LENGTH, /* response_size */
+ isp_page_read_handler, /* page_handler */
+ isp_sys_completion_handler); /* completion_handler */
+ }
+ else
+ {
+ /* SAR 80563
+ * On 060 device. The user should make sure that the all divisor i.e
+ * fclk, pclk0, pclk1 and clk_fic64 divisor must be equal to each other
+ * and set to to divide by 1,2, 4, 8, 16(but not 32).
+ */
+ status = MSS_SYS_CLK_DIVISOR_ERROR;
+ }
+
+ return status;
+}
+
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_initiate_iap
+(
+ uint8_t mode,
+ uint32_t bitstream_spi_addr
+)
+{
+ uint8_t status = MSS_SYS_SUCCESS;
+ uint8_t clk_switch_status = CLOCK_SWITCHING_SUCCESS;
+ uint16_t actual_response_length;
+ uint8_t iap_prog_req[6];
+ uint8_t response[IAP_PROG_SERV_RESP_LENGTH];
+
+ if(mode == MSS_SYS_PROG_VERIFY)
+ {
+ /*
+ * Check fabric digest before performing IAP verify
+ */
+ MSS_SYS_check_digest(MSS_SYS_DIGEST_CHECK_FABRIC);
+ }
+
+ if(mode != MSS_SYS_PROG_AUTHENTICATE)
+ {
+ /*
+ * Keep a copy of the initial eNVM configuration used before IAP was
+ * initiated. The eNVM configuration will be restored, as part of the IAP
+ * completion handler, when IAP completes.
+ */
+ g_initial_envm_cr = SYSREG->ENVM_CR;
+
+ /* Store the MSS DDR FACC 2 register value so that its can be restored back
+ * when the IAP operation is completed.asynchronous_event_handler. */
+ g_initial_mssddr_facc2_cr = SYSREG->MSSDDR_FACC2_CR;
+
+ /*
+ * Set the eNVM's frequency range to its maximum. This is required to ensure
+ * successful eNVM programming on all devices.
+ */
+ SYSREG->ENVM_CR = (g_initial_envm_cr & ~NVM_FREQRNG_MASK) | NVM_FREQRNG_MAX;
+
+ /* Select output of MUX 0, MUX 1 and MUX 2 during standby */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR & ((uint32_t)(FACC_STANDBY_SEL << FACC_STANDBY_SHIFT) | ~FACC_STANDBY_SEL_MASK);
+
+ /* Enable the signal for the 50 MHz RC oscillator */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR | ((uint32_t)(MSS_25_50MHZ_EN << MSS_25_50MHZ_EN_SHIFT) & MSS_25_50MHZ_EN_MASK);
+
+ /* Enable the signal for the 1 MHz RC oscillator */
+ SYSREG->MSSDDR_FACC2_CR = SYSREG->MSSDDR_FACC2_CR | ((uint32_t)(MSS_1MHZ_EN << MSS_1MHZ_EN_SHIFT) & MSS_1MHZ_EN_MASK);
+
+ /* SAR 80563
+ * Cortex-M3 firmware dynamically divides down fclk, pclk0, pclk1 and
+ * clk_fic64 to the divided by 32 versions based on device version.
+ */
+ clk_switch_status = clk_switching_fix();
+ }
+
+ if(clk_switch_status == CLOCK_SWITCHING_SUCCESS)
+ {
+ /*
+ * There is no response for Program mode because the Cortex-M3 will
+ * get reset on completion of the system service.
+ */
+ iap_prog_req[0] = IAP_PROGRAMMING_REQUEST_CMD;
+ iap_prog_req[1] = mode;
+
+ iap_prog_req[2] = (uint8_t)(bitstream_spi_addr);
+ iap_prog_req[3] = (uint8_t)(bitstream_spi_addr >> 8u);
+ iap_prog_req[4] = (uint8_t)(bitstream_spi_addr >> 16u);
+ iap_prog_req[5] = (uint8_t)(bitstream_spi_addr >> 24u);
+
+ signal_request_start();
+
+ MSS_COMBLK_send_cmd(iap_prog_req, /* p_cmd */
+ sizeof(iap_prog_req), /* cmd_size */
+ 0, /* p_data */
+ 0, /* data_size */
+ response, /* p_response */
+ IAP_PROG_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ /*
+ * Handle case where service is not implemented/enabled in the device.
+ */
+ actual_response_length = wait_for_request_completion();
+
+ if((IAP_PROG_SERV_RESP_LENGTH == actual_response_length) &&
+ (IAP_PROGRAMMING_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ if(mode != MSS_SYS_PROG_AUTHENTICATE)
+ {
+ /* Restore back to original value. */
+ SYSREG->ENVM_CR = g_initial_envm_cr;
+ SYSREG->MSSDDR_FACC2_CR = g_initial_mssddr_facc2_cr;
+ }
+ }
+ else
+ {
+ /* SAR 80563
+ * On 060 device. The user should make sure that the all divisor i.e
+ * fclk, pclk0, pclk1 and clk_fic64 divisor must be equal to each other
+ * and set to to divide by 1,2, 4, 8, 16(but not 32).
+ */
+ status = MSS_SYS_CLK_DIVISOR_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_check_digest
+(
+ uint8_t options
+)
+{
+ uint8_t status;
+ uint8_t clk_switch_status = CLOCK_SWITCHING_SUCCESS;
+ uint16_t actual_response_length;
+ uint8_t digest_check_req[2];
+ uint8_t response[DIGEST_CHECK_SERV_RESP_LENGTH];
+
+ /*
+ * The Digest Check system service is not available on M2S050 rev A, rev B and rev C.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+
+ /*
+ * Private ENVM factory digest and user digest is available only on G4X
+ * devices
+ */
+ if((options & 0x30u) != 0x00)
+ {
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ }
+
+ /* SAR 80563
+ * Cortex-M3 firmware dynamically divides down fclk, pclk0, pclk1 and
+ * clk_fic64 to the divided by 32 versions based on device version.
+ */
+ if(MSS_SYS_DIGEST_CHECK_FABRIC == (options & 0x01u))
+ {
+ clk_switch_status = clk_switching_fix();
+ }
+
+ if(clk_switch_status == CLOCK_SWITCHING_SUCCESS)
+ {
+
+ signal_request_start();
+
+ digest_check_req[0] = DIGEST_CHECK_REQUEST_CMD;
+ digest_check_req[1] = options;
+
+ MSS_COMBLK_send_cmd(digest_check_req, /* p_cmd */
+ sizeof(digest_check_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ DIGEST_CHECK_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((DIGEST_CHECK_SERV_RESP_LENGTH == actual_response_length) &&
+ (DIGEST_CHECK_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+ }
+ else
+ {
+ /* SAR 80563
+ * On 060 device. The user should make sure that the all divisor i.e
+ * fclk, pclk0, pclk1 and clk_fic64 divisor must be equal to each other
+ * and set to to divide by 1,2, 4, 8, 16(but not 32).
+ */
+ status = MSS_SYS_CLK_DIVISOR_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_create_activation_code
+(
+ void
+)
+{
+ uint8_t response[PUF_USER_ACTIVATION_CODE_RESP_LENGTH];
+ uint8_t status;
+ uint8_t params;
+ uint8_t key_numbers = 0u;
+
+ /*
+ * The user activation code system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params = PUF_CREATE_USER_ACTIVATION_CODE;
+
+ status = execute_service(PUF_ACTIVATION_CODE_REQUEST_CMD,
+ &params,
+ response,
+ PUF_USER_ACTIVATION_CODE_RESP_LENGTH);
+
+ /*
+ * System controller is locking eNVM-1 while executing create activation
+ * code service, but system controller is not releasing back after
+ * completing the operation. In order to unlock eNVM-1, call get number of
+ * key service. PUF get number of key service will release the eNVM-1 lock
+ * after reading the number of keys enrolled.
+ */
+ MSS_SYS_puf_get_number_of_keys(&key_numbers);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_delete_activation_code
+(
+ void
+)
+{
+ uint8_t response[PUF_USER_ACTIVATION_CODE_RESP_LENGTH];
+ uint8_t status;
+ uint8_t params;
+ uint8_t key_numbers = 0u;
+
+ /*
+ * The user activation code system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params = PUF_DELETE_USER_ACTIVATION_CODE;
+
+ status = execute_service(PUF_ACTIVATION_CODE_REQUEST_CMD,
+ &params,
+ response,
+ PUF_USER_ACTIVATION_CODE_RESP_LENGTH);
+ /*
+ * System controller is locking eNVM-1 while executing delete activation
+ * code service, but system controller is not releasing back after
+ * completing the operation. In order to unlock eNVM-1, call get number of
+ * key service. PUF get number of key service will release the eNVM-1 lock
+ * after reading the number of keys enrolled.
+ */
+ MSS_SYS_puf_get_number_of_keys(&key_numbers);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_get_number_of_keys
+(
+ uint8_t* p_number_of_keys
+)
+{
+ uint8_t response[6u] = { 0x00 };
+ uint8_t params[11u] = { 0x00 };
+ uint8_t status;
+
+ /*
+ * The user key code system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params[0] = PUF_GET_NUMBER_OF_KC_SUBCOMMAND;
+
+ status = execute_service(PUF_USER_KEY_CODE_REQUEST_CMD,
+ params,
+ response,
+ PUF_GET_NUMBER_OF_KEYS_RESP_LENGTH);
+
+ *p_number_of_keys = params[9];
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_enroll_key
+(
+ uint8_t key_number,
+ uint16_t key_size,
+ uint8_t* p_key_value,
+ uint8_t* p_key_location
+)
+{
+ uint8_t response[6u];
+ uint8_t params[11u];
+ uint8_t status;
+ uint8_t key_numbers = 0u;
+
+ /*
+ * The PUF enroll key system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ if(p_key_value == 0)
+ {
+ params[0] = PUF_CREATE_INT_KC_SUBCOMMAND;
+ }
+ else
+ {
+ params[0] = PUF_CREATE_EXT_KC_SUBCOMMAND;
+ }
+
+ write_ptr_value_into_array(p_key_location, params, 1u);
+ write_ptr_value_into_array(p_key_value, params, 5u);
+
+ params[9] = key_number;
+ params[10] = key_size;
+
+ status = execute_service(PUF_USER_KEY_CODE_REQUEST_CMD,
+ params,
+ response,
+ PUF_ENROLL_KEYS_RESP_LENGTH);
+
+ /*
+ * System controller is locking eNVM-1 while executing create key code
+ * service, but system controller is not releasing back after completing the
+ * operation. In order to unlock eNVM-1, call get number of key service. PUF
+ * get number of key service will release the eNVM-1 lock after reading the
+ * number of keys enrolled.
+ */
+ MSS_SYS_puf_get_number_of_keys(&key_numbers);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_delete_key
+(
+ uint8_t key_number
+)
+{
+ uint8_t response[6u];
+ uint8_t params[11u];
+ uint8_t status;
+ uint8_t key_numbers = 0u;
+
+ /*
+ * The delete PUF key system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params[0] = PUF_DELETE_KC_SUBCOMMAND;
+ params[9] = key_number;
+
+ status = execute_service(PUF_USER_KEY_CODE_REQUEST_CMD,
+ params,
+ response,
+ PUF_ENROLL_KEYS_RESP_LENGTH);
+
+ /*
+ * System controller is locking eNVM-1 while executing delete key code
+ * service, but system controller is not releasing back after completing the
+ * operation. In order to unlock eNVM-1, call get number of key service. PUF
+ * get number of key service will release the eNVM-1 lock after reading the
+ * number of keys enrolled.
+ */
+ MSS_SYS_puf_get_number_of_keys(&key_numbers);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_fetch_key
+(
+ uint8_t key_number,
+ uint8_t ** pp_key
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[5];
+ uint8_t status;
+
+ /*
+ * The fetch user key system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ write_ptr_value_into_array(*pp_key, params, 0u);
+
+ params[4] = key_number;
+
+ status = execute_service(PUF_FETCH_KEY_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+ if(pp_key != NULL)
+ {
+ write_array_into_ptr_value(&(*pp_key), params, 0);
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_export_keycodes
+(
+ uint8_t * p_keycodes
+)
+{
+ uint8_t response[PUF_EXPORT_ALL_KEYCODES_RESP_LENGTH];
+ uint8_t params[11u];
+ uint8_t status;
+
+ /*
+ * The export all user key system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params[0] = PUF_EXPORT_ALL_KC_SUBCOMMAND;
+
+ write_ptr_value_into_array(p_keycodes, params, 1u);
+
+ status = execute_service(PUF_USER_KEY_CODE_REQUEST_CMD,
+ params,
+ response,
+ PUF_EXPORT_ALL_KEYCODES_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_import_keycodes
+(
+ uint8_t * p_keycodes
+)
+{
+ uint8_t response[PUF_IMPORT_ALL_KEYCODES_RESP_LENGTH];
+ uint8_t params[11u];
+ uint8_t status;
+
+ /*
+ * The import all key code system service is not available on M2S050 rev A,
+ * rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ params[0] = PUF_IMPORT_ALL_KC_SUBCOMMAND;
+
+ write_ptr_value_into_array(p_keycodes, params, 1u);
+
+ status = execute_service(PUF_USER_KEY_CODE_REQUEST_CMD,
+ params,
+ response,
+ PUF_IMPORT_ALL_KEYCODES_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_fetch_ecc_public_key
+(
+ uint8_t* p_puf_public_key
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[4];
+ uint8_t status;
+
+ /*
+ * The fetch puf ecc public key system service is not available on M2S050
+ * rev A, rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ write_ptr_value_into_array(p_puf_public_key, params, 0u);
+
+ status = execute_service(PUF_ECC_PUBLIC_KEY_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_puf_get_random_seed
+(
+ uint8_t* p_puf_seed
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[4];
+ uint8_t status;
+
+ /*
+ * The get puf seed system service is not available on M2S050 rev A, rev B,
+ * rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ write_ptr_value_into_array(p_puf_seed, params, 0u);
+
+ status = execute_service(PUF_SEED_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_ecc_point_multiplication
+(
+ uint8_t* p_scalar_d,
+ uint8_t* p_point_p,
+ uint8_t* p_point_q
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[12];
+ uint8_t status;
+
+ /*
+ * The ECC point multiplication system service is not available on M2S050
+ * rev A, rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ write_ptr_value_into_array(p_scalar_d, params, 0u);
+ write_ptr_value_into_array(p_point_p, params, 4u);
+ write_ptr_value_into_array(p_point_q, params, 8u);
+
+ status = execute_service(POINT_MULTIPLICATION_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_ecc_point_addition
+(
+ uint8_t* p_point_p,
+ uint8_t* p_point_q,
+ uint8_t* p_point_r
+)
+{
+ uint8_t response[STANDARD_SERV_RESP_LENGTH];
+ uint8_t params[12];
+ uint8_t status;
+
+ /*
+ * The ECC point addition system service is not available on M2S050
+ * rev A, rev B, rev C and rev D.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ write_ptr_value_into_array(p_point_p, params, 0u);
+ write_ptr_value_into_array(p_point_q, params, 4u);
+ write_ptr_value_into_array(p_point_r, params, 8u);
+
+ status = execute_service(POINT_ADDITION_REQUEST_CMD,
+ params,
+ response,
+ STANDARD_SERV_RESP_LENGTH);
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+void MSS_SYS_ecc_get_base_point
+(
+ uint8_t* p_point_g
+)
+{
+ const uint8_t base_point_g[] =
+ {
+ 0xaa, 0x87, 0xca, 0x22, 0xbe, 0x8b, 0x05, 0x37, 0x8e, 0xb1, 0xc7, 0x1e,
+ 0xf3, 0x20, 0xad, 0x74, 0x6e, 0x1d, 0x3b, 0x62, 0x8b, 0xa7, 0x9b, 0x98,
+ 0x59, 0xf7, 0x41, 0xe0, 0x82, 0x54, 0x2a, 0x38, 0x55, 0x02, 0xf2, 0x5d,
+ 0xbf, 0x55, 0x29, 0x6c, 0x3a, 0x54, 0x5e, 0x38, 0x72, 0x76, 0x0a, 0xB7,
+ 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+ 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+ 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+ 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5F
+ };
+
+ memcpy(p_point_g, &base_point_g[0], sizeof(base_point_g));
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_start_clock_monitor
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * The Start clock monitoring tamper Control service is available only on
+ * G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x01u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_stop_clock_monitor
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * The Stop clock monitoring tamper Control service is available only on
+ * G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x02u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_enable_puf_power_down
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * The Enable PUF power down service is available only on G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x04u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_disable_puf_power_down
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * Disable PUF power down is available only on G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x08u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_clear_lock_parity
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * The Clear Lock parity is available only on G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x10u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ * See mss_sys_services.h for details.
+ */
+uint8_t MSS_SYS_clear_mesh_short
+(
+ void
+)
+{
+ uint8_t status;
+ uint8_t tamper_control_req[2];
+ uint8_t response[TAMPER_CONTROL_SERV_RESP_LENGTH];
+ uint16_t actual_response_length;
+
+ /*
+ * The Clear mesh short service is available only on G4X device.
+ */
+ ASSERT(0x0000F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0001F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0002F802u != SYSREG->DEVICE_VERSION);
+ ASSERT(0x0003F802u != SYSREG->DEVICE_VERSION);
+
+ signal_request_start();
+
+ tamper_control_req[0] = TAMPER_CONTROL_REQUEST_CMD;
+ tamper_control_req[1] = 0x20u;
+
+ MSS_COMBLK_send_cmd(tamper_control_req, /* p_cmd */
+ sizeof(tamper_control_req), /* cmd_size */
+ 0, /* p_data */
+ 0u, /* data_size */
+ response, /* p_response */
+ TAMPER_CONTROL_SERV_RESP_LENGTH, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((TAMPER_CONTROL_SERV_RESP_LENGTH == actual_response_length) &&
+ (TAMPER_CONTROL_REQUEST_CMD == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ *
+ */
+static uint8_t execute_service
+(
+ uint8_t cmd_opcode,
+ uint8_t * cmd_params_ptr,
+ uint8_t * response,
+ uint16_t response_length
+)
+{
+ uint8_t status;
+ uint16_t actual_response_length;
+
+ signal_request_start();
+
+ MSS_COMBLK_send_cmd_with_ptr(cmd_opcode, /* cmd_opcode */
+ (uint32_t)cmd_params_ptr, /* cmd_params_ptr */
+ response, /* p_response */
+ response_length, /* response_size */
+ request_completion_handler); /* completion_handler */
+
+ actual_response_length = wait_for_request_completion();
+
+ if((response_length == actual_response_length) && (cmd_opcode == response[0]))
+ {
+ status = response[1];
+ }
+ else
+ {
+ status = MSS_SYS_UNEXPECTED_ERROR;
+ }
+
+ return status;
+}
+
+/*==============================================================================
+ *
+ */
+static void request_completion_handler
+(
+ uint8_t * p_response,
+ uint16_t response_size
+)
+{
+ g_request_in_progress = 0u;
+ g_last_response_length = response_size;
+}
+
+/*==============================================================================
+ *
+ */
+static void signal_request_start(void)
+{
+ /* Wait for current request to complete. */
+ while(g_request_in_progress)
+ {
+ ;
+ }
+
+ g_request_in_progress = 1u;
+ g_last_response_length = 0u;
+}
+
+/*==============================================================================
+ *
+ */
+static uint16_t wait_for_request_completion(void)
+{
+ while(g_request_in_progress)
+ {
+ ;
+ }
+
+ return g_last_response_length;
+}
+
+/*==============================================================================
+ *
+ */
+static void write_ptr_value_into_array
+(
+ const uint8_t * pointer,
+ uint8_t target_array[],
+ uint32_t array_index
+)
+{
+ target_array[array_index] = (uint8_t)((uint32_t)pointer);
+ target_array[array_index + 1] = (uint8_t)((uint32_t)pointer >> 8u);
+ target_array[array_index + 2] = (uint8_t)((uint32_t)pointer >> 16u);
+ target_array[array_index + 3] = (uint8_t)((uint32_t)pointer >> 24u);
+}
+
+/*==============================================================================
+ Function to write array address to pointer location.
+ */
+static void write_array_into_ptr_value
+(
+ uint8_t** pointer,
+ uint8_t target_array[],
+ uint32_t array_index
+)
+{
+ uint32_t var;
+
+ var = (uint32_t)target_array[array_index + 3];
+ var = ((var << 8u) & 0xFFFFFF00) | target_array[array_index + 2];
+ var = ((var << 8u) & 0xFFFFFF00) | target_array[array_index + 1];
+ var = ((var << 8u) & 0xFFFFFF00) | target_array[array_index];
+
+ *pointer = (uint8_t*)var;
+}
+
diff --git a/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.h b/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.h
new file mode 100644
index 0000000000..b2586e0e5b
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_sys_services/mss_sys_services.h
@@ -0,0 +1,2500 @@
+/*******************************************************************************
+ * (c) Copyright 2012-2016 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 MSS System Services bare metal software driver public API.
+ *
+ * SVN $Revision: 8680 $
+ * SVN $Date: 2016-11-25 14:18:13 +0530 (Fri, 25 Nov 2016) $
+ */
+
+/*=========================================================================*//**
+ @mainpage SmartFusion2 MSS System Services Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The SmartFusion2 microcontroller subsystem (MSS) includes a communication
+ block (COMM_BLK) allowing it to communicate with the SmartFusion2 System
+ Controller. The SmartFusion2 System Controller performs a variety of system
+ wide services. This software driver provides a set of functions to access
+ these System Services. 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 the
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependencies
+ The MSS System Services driver does not require any configuration. It relies
+ on the SmartFusion2 communication block (MSS_COMM_BLK) to communicate with the
+ System Controller. The MSS_COMM_BLK is always enabled.
+ The base address, register addresses and interrupt number assignment for the
+ MSS_COMM_BLK are defined as constants in the SmartFusion2 CMSIS HAL. You must
+ ensure that the latest SmartFusion2 CMSIS HAL is included in the project
+ settings of the software tool chain used to build your project and that it is
+ generated into your project.
+
+ @section theory_op Theory of Operation
+ The System Services driver provides access to the SmartFusion2 System
+ Controller services. These system services are loosely grouped into the
+ following features:
+ - Reading system information
+ - Cryptography
+ - Non-deterministic random bit generator
+ - Flash*Freeze
+ - Zeroization
+ - Asynchronous Messages
+ - Programming Services
+ - Digest Check Service
+ Note: Refer to the function descriptions for further details about the
+ features of each individual service.
+
+ Reading System Information
+ The System Services driver can be used to read information about the
+ SmartFusion2 device and the design programmed into it using the following
+ functions:
+ - MSS_SYS_get_serial_number()
+ - MSS_SYS_get_user_code()
+ - MSS_SYS_get_design_version()
+ - MSS_SYS_get_device_certificate()
+ - MSS_SYS_get_secondary_device_certificate()
+
+ Cryptography Services
+ The System Services driver provides cryptographic services using the following
+ functions:
+ - MSS_SYS_128bit_aes()
+ - MSS_SYS_256bit_aes()
+ - MSS_SYS_sha256()
+ - MSS_SYS_hmac()
+ - MSS_SYS_challenge_response()
+ - MSS_SYS_key_tree()
+
+ Non-Deterministic Random Bit Generator
+ The System Services driver provides random number generation services using
+ the following functions:
+ - MSS_SYS_nrbg_instantiate()
+ - MSS_SYS_nrbg_self_test()
+ - MSS_SYS_nrbg_generate()
+ - MSS_SYS_nrbg_reseed()
+ - MSS_SYS_nrbg_uninstantiate()
+ - MSS_SYS_nrbg_reset()
+
+ Flash*Freeze
+ The System Services driver can be used to request the system to enter
+ Flash*Freeze mode using the following function:
+ - MSS_SYS_flash_freeze()
+ The System Controller sends an asynchronous message to the MSS COMM_BLK when
+ the device is either about to enter or has exited Flash*Freeze mode. The
+ MSS_SYS_init() function can register a callback function with the System
+ Services driver to handle these asynchronous messages.
+
+ Zeroization
+ The System Service driver can be used to destroy sensitive information on the
+ SmartFusion2 device using the following function.
+ - MSS_SYS_zeroize_device()
+ The zeroization system service erases all user configuration data, user keys,
+ user security settings, NVM, SRAM, FPGA flip-flops, System Controller memory,
+ and crypto-engine registers. The zeroization system service is enabled and
+ configured in the Libero hardware flow.
+ Note: The zeroization system service can render the SmartFusion2 device
+ permanently and irrevocably disabled depending on the configuration
+ selected in the Libero hardware flow.
+
+ Asynchronous Messages
+ The System Controller sends asynchronous messages to the MSS COMM_BLK when
+ certain events are detected during the execution of the following system
+ services:
+ �Flash*Freeze
+ �Power-on-reset (POR) digest check
+ �Tamper detect events
+ The MSS_SYS_init() function can register a callback function with the System
+ Services driver to handle these asynchronous messages allowing the user
+ application code to take remedial or defensive action. If the application
+ code does not provide an asynchronous event handler function then the driver
+ simply reads and discards these asynchronous messages.
+ Flash*Freeze Entry and Exit
+ The System Controller sends a Flash*Freeze entry or exit message to the MSS
+ COMM_BLK when the SmartFusion2 device is either about to enter or has exited
+ Flash*Freeze mode. The driver passes the entry/exit message opcode as a
+ parameter to the event handler callback function.
+ Power-on Reset (POR) Digest Error
+ The POR digest check service is enabled in the Libero hardware flow and if
+ enabled is automatically performed as part of the device�s power up sequence.
+ The System Controller sends a POR digest check error message to the MSS
+ COMM_BLK when the result of the POR digest check is a mismatch between the
+ original stored digest and the current digest. The driver passes the command
+ byte and the error flags byte from the error message as parameters to the
+ event handler callback function.
+ Tamper detect events
+ The System Controller sends tamper message to the MSS COMM_BLK when the
+ tamper event is detected. This tamper message is of one byte contain only
+ command opcode. The driver pass the tamper message opcode as a parameter
+ to the event handler callback function.
+
+ Programming Service
+ The In-System Programming (ISP) system service can be used for field upgrades
+ of the hardware design programmed in the FPGA fabric. The application program
+ running on the Cortex-M3 controls the ISP operations, it must retrieve the
+ programming file from memory or from a communication port and feed it to
+ the System Controller through the ISP system service. The System Controller
+ performs the actual programming of the FPGA (fabric and eNVM) using the
+ programming data it receives from the Cortex-M3 as part of the ISP system
+ service.
+ Programming files are large and cannot always be entirely retrieved by the
+ application before starting the ISP operation. The ISP system service is
+ designed to work around this issue by handling programming one page at a
+ time. The application initiates the ISP operation through a call to
+ MSS_SYS_start_isp(), passing two function pointers as parameters. These two
+ function pointers point to a page read handler function and an ISP completion
+ handler function that must be implemented as part of the application. The
+ system services driver will call the application�s page read handler
+ function every time it is ready to program the FPGA with a new page of
+ programming data. The page read handler function is responsible for splitting
+ the programming file into suitably sized pages. The page size is not fixed
+ and can be chosen to suit the application. The system services driver will
+ call the ISP completion handler function once the last page has been
+ programmed.
+ The application must keep track of the pages of programming data is has
+ passed to the ISP system service. It must provide the location of the next
+ programming page by writing the address of the page into the location
+ pointed to by the pp_next_page pointer passed as parameter to the page read
+ handler function. The page read handler must return the size of the page or
+ zero if the last page has already been given to the ISP system service.
+
+ The In-Application Programming (IAP) system service provides another field
+ upgrade method of the hardware design programmed in FPGA fabric. Using this
+ method, the user application first writes the FPGA fabric design into the SPI
+ Flash connected to MSS SPI-0 before invoking the IAP system service. The FPGA
+ fabric is then programmed under control of the SmartFusion2 system controller
+ without intervention of the Cortex-M3 processor. The application must
+ configure the SPI peripheral and provide exclusive access to the IAP service
+ before invoking the IAP system service.
+ When the IAP service is invoked, the system controller will send the SPI
+ command 0Bh i.e. single read operation command to the SPI flash to retrieve
+ the FPGA fabric design. The system controller will perform one of the
+ following operations based on the mode selected when invoking the service:
+ a) Authenticate the fabric design.
+ b) Program the fabric design into FPGA.
+ c) Verify that the programming was successful.
+ The system controller will take 2 to 3 minutes to complete each operation.
+ The application must provide the starting location address of the new FPGA
+ fabric design present in SPI Flash when invoking the IAP service.
+ The system controller will return a response indicating the status of the
+ operation on completing the execution of the IAP service except in the case
+ of successful programming. The system controller will reset the device and
+ start execution of the new FPGA fabric design after successfully programming
+ the device. The system controller will not return any response information
+ when a successful programming operation completes.
+
+ Digest Check Service
+ The System Service driver can be used to recalculate and compare digests of
+ selected components using the following function.
+ - MSS_SYS_check_digest()
+ Note: This function is not used for the power-on-reset (POR) digest check
+ service. An asynchronous event handler registered with the
+ MSS_SYS_init() function is used to support the POR digest check
+ service.
+
+ Elliptic Curve services
+ The System Service driver can be used to perform elliptic curve cryptography
+ (ECC) mathematical operations over the field defined by the NIST P-384
+ curve. point addition and point multiplication using the following functions
+ are provided:
+ - MSS_SYS_ecc_point_multiplication()
+ - MSS_SYS_ecc_point_addition()
+ - MSS_SYS_ecc_get_base_point()
+ One example use of these functions is the elliptic curve Diffie-Hellman
+ (ECDH) key establishment protocol. In this protocol, a public key is computed
+ by performing a point multiplication of a 384-bit private key with the base
+ point for the NIST P-384 curve. Both parties involved in the key
+ establishment compute their public keys and send them to each other. A shared
+ secret is established by point multiplication of each party�s private key
+ with the remote party�s public key. The elliptic curve mathematical
+ properties ensure that the private key point multiplication with the remote
+ party�s public key results in the same point on the curve for both parties.
+ The coordinates of this point on the curve is used as the shared secret for
+ further cryptographic operations.
+ Note: There is no checking done to see if the given input point or points
+ are valid points on the elliptic curve. Supplying illegal X-Y coordinates
+ for a point will result in a garbage output. However, if a valid point or
+ points are given, then the resulting output point is guaranteed to be valid.
+
+ PUF Services
+ The SRAM-PUF system services provide a Physically Unclonable Function (PUF)
+ that can be used for key generation and storage as well as device
+ authentication.
+ The large SmartFusion2 devices starting from the M2S060 include an SRAM-PUF
+ hardware block as part of the System Controller. This hardware block makes
+ use of a 16Kbit SRAM block to determine an intrinsic secret unique to each
+ device. This intrinsic secret is in turn used to regenerate keys enrolled
+ with the SRAM-PUF hardware block.
+ The SRAM-PUF is also used in design security. Although the system services
+ are not used for design security, it is possible to retrieve the design
+ security ECC public key for device authentication purpose.
+ The SRAM-PUF start-up value can also be used to generate a random number
+ generator seed.
+ Note: PUF service should be executed from DDR/SRAM/eNVM-0 except for the
+ M2S060 device. On the M2S060 device, PUF service should be executed
+ from DDR/SRAM.
+
+ Activation Code
+ An activation code is required by the SRAM-PUF to regenerate the intrinsic
+ secret from the SRAM-PUF start-up value. The start-up value of the PUF�s SRAM
+ block is slightly different from one power-up to the next. Some processing is
+ performed on the PUF�s SRAM start-up value to eliminate randomness and
+ retrieve the exact same intrinsic secret on each power-up cycle. This
+ processing is performed using the activation code, which can be thought of as
+ parity bits that are used to reconstruct the same PUF intrinsic secret each
+ time, in spite of the fact that some SRAM bits are flipped compared to the
+ original snapshot used when the activation code was first enrolled.
+ The devices are shipped with one activation code that was enrolled during
+ the manufacturing process. The PUF secret computed from this enrollment is
+ used to protect a 376-bit ECC private key that may be used for design
+ security purposes as described elsewhere. The user may optionally enroll a
+ second activation code in special �S� -suffix (i.e., security enabled)
+ devices. The activation code is usually generated only once, typically when
+ the system containing the SmartFusion2 device is being commissioned, using a
+ JTAG or SPI programming command. Alternatively, the activation code is
+ created using the following system service function:
+
+ - MSS_SYS_puf_create_activation_code()
+ This might be used if the first user activation code were intentionally
+ deleted and a new one was desired. The activation code is stored the System
+ Controller�s private eNVM after being created. Its value is never exported in
+ clear text from the System Controller. Because of the inherent noise in each
+ SRAM start-up, there is a negligible probability two activation codes or the
+ associated PUF intrinsic secret are ever the same, even if the same device is
+ repeatedly re-enrolled.
+ The activation code can later be destroyed using the following function:
+ - MSS_SYS_puf_delete_activation_code()
+ This function would typically only be used when the system containing
+ SmartFusion2 is being decommissioned or repurposed.
+
+ Enrolling Keys
+ The SRAM-PUF can be used to store cryptographic keys. The keys are stored in
+ such a way that the key�s actual value never appears in the system unless it
+ is retrieved by the user. A so-called "Key Code" is stored in the System
+ Controller�s private eNVM instead of the key�s value. The key code is
+ generated when a key is enrolled. The key code value is created from the
+ enrolled key�s value and the intrinsic secret value. The key�s value can then
+ later be regenerated from the key code value and intrinsic secret value upon
+ user request.
+ NOTE:Note: Key #0 and key #1 are used for design security and are not
+ accessible to the user. Key Code #2 may be used to store a user
+ data security key, but has an important optional use in JTAG- or
+ SPI-based key validation, as will be described below.
+
+ The enrolled keys can be intrinsic keys or extrinsic keys. The value of an
+ intrinsic key is a random number generated from the SRAM-PUF start-up value.
+ Intrinsic keys are useful where a security protocol executing on SmartFusion2
+ needs to generate a key�s value and store it for later use. For example, the
+ user could request a 384-bit long intrinsic key to be enrolled and use it as
+ private key in an elliptic curve Diffie-Hellman key exchange.
+ The value of an extrinsic key is specified by the user. For example, the user
+ could request a symmetric key obtained from a key exchange protocol to be
+ enrolled for later use.
+ The following functions are used for key enrollment:
+ - MSS_SYS_puf_get_number_of_keys()
+ - MSS_SYS_puf_enroll_key()
+ - MSS_SYS_puf_fetch_key()
+ - MSS_SYS_puf_delete_key()
+
+ Keys are identified by a number and must be enrolled sequentially. Key codes
+ #0 and #1 are reserved as a 256-bit symmetric extrinsic key and a 384-bit
+ private (asymmetric) intrinsic key, both used for design security only, and
+ are enrolled by JTAG (or SPI) programming commands. These commands also
+ enroll the user activation code and key code #2, a 256-bit value that has a
+ special use in key validation, and which is enrolled at the same time as key
+ code #1, as will be described below.
+ The first step in enrolling a new key is to determine how many keys are
+ already enrolled. This is achieved by a call to function
+ MSS_SYS_puf_get_number_of_keys() which returns the number of enrolled keys.
+ Keys are numbered from 0 up to 57 (the maximum number of keys assuming all
+ user keys are less than or equal to 256 bits in length). For example,
+ assuming only the first three key codes mentioned above have been enrolled
+ using the JTAG programming commands, the value returned would be �3�. The
+ number of keys returned by MSS_SYS_puf_get_number_of_keys() can then be used
+ as the newly enrolled key identification number since key numbering is zero
+ based. Thus, the first data security key enrolled by the user would generate
+ key code #3.
+
+ A key is enrolled through a call to function MSS_SYS_puf_enroll_key(). This
+ function takes the following parameters:
+ � The key identification number that will be used to later retrieve the
+ key�s value. This is the value returned by a call to
+ MSS_SYS_puf_get_number_of_keys().
+ � The key size.
+ � A pointer to the buffer containing the value of the key to enroll. The
+ value of this pointer must be NULL if enrolling an intrinsic key where
+ the SRAM-PUF will generate the actual key value.
+ � A pointer to the buffer where the enrolled key will be regenerated when
+ later fetched by the user.
+
+ The value of the enrolled keys can be regenerated through a call to function
+ MSS_SYS_puf_fetch_key(). The identification number of the key to fetch is
+ passed as parameter to this function. The requested key�s value will be
+ regenerated and copied to the buffer specified during key enrollment. The
+ key�s value is then available for use until it is no further required and
+ wiped, by the user�s application, from the memory buffer it was fetched into.
+
+ Note: It is not possible to fetch a key if the key codes have been exported
+ and not re-imported.
+
+ A key can be removed from the system through a call to function
+ MSS_SYS_puf_delete_key(). This function only requires the key identification
+ number to specify which key should be removed from the SRAM-PUF.
+
+ Note: If a new key is enrolled in a key-slot where a key was previously
+ enrolled and deleted and which is not the highest key number enrolled,
+ it must be the same size as the key it replaced or an error will be
+ reported.
+
+ Exporting and Importing Key Codes
+ The activation code and key codes used to regenerate the enrolled keys can be
+ exported out of the SRAM-PUF. The exported activation code and key codes are
+ encrypted using a one-time pad. The one-time pad is stored in the System
+ Controller�s private eNVM and is never exported. This means that the exported
+ activation and key codes can only be decrypted by the unique device that
+ exported them.
+ The activation and key code values stored in eNVM are replaced with hash
+ values of themselves as part of the export procedure. This means that
+ enrolled keys cannot be regenerated anymore after the activation and key
+ codes have been exported. The enrolled keys will only be regenerated
+ successfully if the exported activation and key codes for that unique
+ SmartFusion2 device are imported back.
+
+ The activation and all the key codes are exported in one single operation
+ using the following function:
+ - MSS_SYS_puf_export_keycodes()
+ The MSS_SYS_puf_export_keycodes() function can only be called once since the
+ activation and key codes are not present anymore in the device after this
+ function completes. The activation and key codes must be imported back
+ before they can be exported again.
+ The activation and all the key codes are imported back in one single
+ operation using the following function:
+ - MSS_SYS_puf_import_keycodes()
+ It is only possible to import activation and key codes exported from the
+ same unique device. The imported activation and key codes are decrypted
+ using the one-time pad stored in eNVM used during the export procedure.
+ The decrypted activation and key codes are then checked again the hash
+ values stored in place of the activation and key codes. The activation
+ and key codes will only be successfully imported back if the hash values
+ for the imported activation and key codes match the hash values stored in
+ eNVM during the export procedure. Imported activation and key codes are
+ never again restored to non-volatile memory; rather, they are imported to
+ volatile scratch-pad memory, used to regenerate a key, and then deleted.
+ Therefore, they must be re-imported each time a key is needed.
+
+ Retrieving the Design Security ECC Public Key
+ When the 384 bit user design security private ECC key is intrinsically
+ generated and key code #1 is stored using the JTAG or SPI programming
+ commands, the associated 768 bit public key is also generated and stored
+ in the system controller�s private eNVM. At the same time, the256 bit SHA-256
+ hash of the ECC public key is enrolled to key code #2.
+ The 768 bit design security ECC public key can be retrieved using the following
+ system service function:
+ - MSS_SYS_puf_fetch_ecc_public_key()
+ Note that the public key is also exported via JTAG (or SPI) programming
+ commands when it is used in ECDH design security operations such as
+ bitstream encryption or device authentication.
+
+ In order to mitigate man-in-the-middle attacks on the public key when it is
+ exported and used, it is recommended that the ECC public key is validated
+ using an already trusted key. This could be a user design security key, for
+ example. Perhaps the most convenient keys to use are one of the Microsemi
+ certified ECC key pairs, which are trusted because of the verifiable
+ Microsemi signatures on the X.509 public key certificates. This is why when
+ the 384 bit user ECC private key was generated and stored using key code #1,
+ the 256 bit hash of the associated 768 bit public key was stored using key
+ code #2. The JTAG (or SPI) key verification protocol has a special option
+ which includes the value stored in key code #2 in the computation. Thus,
+ besides also validating the device really �knows� the already trusted key,
+ with this option selected, the 256-bit value stored using key code #2 is also
+ validated. If this is the hash of the user ECC public key, then it is proved
+ that the public key is the authentic public key as stored in the device, and
+ not one supplied by an adversary in a man-in-the-middle attack on this key.
+ After the user ECC public key has been thus validated, key code #2 can be
+ deleted and replaced with another 256-bit value the user wishes to validate,
+ such as the hash of user data security key. It is recommended that key code
+ #2 only be used to store hashes of critical security parameters such as
+ secret or private keys, and not the actual secrets, themselves.
+ Note: The user's application need to reserve a defined block of SRAM when
+ using PUF system services, to prevent the compiler from using the SRAM
+ memory range from address 0x2000800 to 0x2000802F inclusive. This is
+ the default location used by the system controller to automatically
+ enroll KC#2, when KC#1 is enrolled.
+
+ Random Number Generator Seed
+ The PUF�s SRAM start-up value randomness can be harvested to generate a
+ 256-bit full entropy true random seed. A random seed can be obtained using
+ function:
+ - MSS_SYS_puf_get_random_seed()
+ Note: Random seeds can only be generated after the SRAM-PUF has been powered
+ -down for 250 msec. Thus, if the PUF has been used more recently than
+ that, there may be a delay before the seed is generated.
+
+ Tamper control service
+ The tamper control system services provide the following services:
+ - Enable/disable clock monitoring
+ - Control power to PUF
+ - Clear mesh short tamper
+ - Clear lock parity tamper
+
+ The tamper control services are accessed using the following functions:
+ - MSS_SYS_start_clock_monitor()
+ - MSS_SYS_stop_clock_monitor()
+ - MSS_SYS_enable_puf_power_down()
+ - MSS_SYS_disable_puf_power_down()
+ - MSS_SYS_clear_lock_parity()
+ - MSS_SYS_clear_mesh_short()
+
+ *//*=========================================================================*/
+
+#ifndef __MSS_SYS_SERVICES_H_
+#define __MSS_SYS_SERVICES_H_ 1
+
+#include "../../CMSIS/m2sxxx.h"
+#include "mss_comblk_page_handler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==============================================================================
+ * Status codes:
+ */
+/*-------------------------------------------------------------------------*//**
+ These constants are used by multiple services to communicate the outcome of a
+ system services request. These status codes are used across all types of
+ services.
+
+ - MSS_SYS_SUCCESS:
+ Indicates that the system services completed successfully.
+
+ - MSS_SYS_UNEXPECTED_ERROR:
+ Indicates that the system failed in an unexpected way.
+
+ - MSS_SYS_MEM_ACCESS_ERROR:
+ Indicates that the System Controller could not access the memory used to
+ pass parameters to the System Controller or to return a service result to
+ the Cortex-M3.
+
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY:
+ Indicates that the requested system service is not available on the
+ SmartFusion2 device.
+
+ - MSS_SYS_SERVICE_DISABLED_BY_USER:
+ Indicates that the requested system service has been disabled as part of
+ the hardware design.
+
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ Indicates that the license is not available in SmartFusion2 device for
+ this service.
+
+ - MSS_SYS_CLK_DIVISOR_ERROR
+ Indicates that on 060 device the divisor values for fclk, pclk0, pclk1,
+ clk_fic64 are not equal to each other or the divisor values is set to
+ divide by 32.
+ */
+#define MSS_SYS_SUCCESS 0u
+#define MSS_SYS_UNEXPECTED_ERROR 200u
+#define MSS_SYS_CLK_DIVISOR_ERROR 201u
+
+#define MSS_SYS_MEM_ACCESS_ERROR 127u
+#define MSS_SYS_SERVICE_NOT_LICENSED 253u
+#define MSS_SYS_SERVICE_DISABLED_BY_FACTORY 254u
+#define MSS_SYS_SERVICE_DISABLED_BY_USER 255u
+
+/*-------------------------------------------------------------------------*//**
+ These constants are used by PUF services to communicate the outcome of a
+ system services request. These status codes are only used by PUF services.
+
+ - MSS_SYS_ENVM_ERROR:
+ Indicates that a eNVM error occurred for both create and delete user
+ activation code sub command.
+
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING:
+ Indicates that PUF error occur while creating new user activation code.
+
+ - MSS_SYS_INVALID_SUBCMD:
+ Indicates that the sub command is invalid.
+
+ - MSS_SYS_INVALID_REQUEST_OR_KC:
+ Indicates that request or Key code is invalid, when exporting or
+ importing.
+
+ - MSS_SYS_INVALID_KEYNUM_OR_ARGUMENT
+ Indicates that the supplied key number or argument is invalid.
+
+ - MSS_SYS_NO_VALID_PUBLIC_KEY
+ Indicates that no valid public key present in eNVM.
+
+ - MSS_SYS_INVALID_MEMORY_ADDRESS:
+ Indicates that memory address is invalid.
+
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ Indicates that the eNVM program error occur when writing to the private eNVM
+ for both create and delete user activation code sub command.
+
+ - MSS_SYS_INVALID_HASH:
+ Indicates that 32 byte hash is invalid.
+
+ - MSS_SYS_INVALID_USER_AC1:
+ Indicates that invalid user activation code has been imported.
+
+ - MSS_SYS_ENVM_VERIFY_ERROR:
+ Indicates that the eNVM verify error occur when writing to the private eNVM
+ for both create and delete user activation code sub command.
+
+ - MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC:
+ Indicates that the supplied key size is incorrect while renewing the key
+ code.
+
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH:
+ Indicates that digest mismatch occurs for private eNVM.
+
+ - MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD:
+ Indicate that the sub command is invalid.
+
+ - MSS_SYS_DRBG_ERROR:
+ Indicates that DRBG error occurred while populating one time pad reminder
+ by random bits.
+*/
+#define MSS_SYS_ENVM_ERROR 1u
+#define MSS_SYS_PUF_ERROR_WHEN_CREATING 2u
+#define MSS_SYS_INVALID_SUBCMD 3u
+#define MSS_SYS_INVALID_REQUEST_OR_KC 3u
+#define MSS_SYS_INVALID_KEYNUM_OR_ARGUMENT 3u
+#define MSS_SYS_NO_VALID_PUBLIC_KEY 3u
+#define MSS_SYS_INVALID_MEMORY_ADDRESS 4u
+#define MSS_SYS_ENVM_PROGRAM_ERROR 4u
+#define MSS_SYS_INVALID_HASH 5u
+#define MSS_SYS_INVALID_USER_AC1 6u
+#define MSS_SYS_ENVM_VERIFY_ERROR 7u
+#define MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC 8u
+#define MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH 10u
+#define MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD 11u
+#define MSS_SYS_DRBG_ERROR 12u
+
+/*-------------------------------------------------------------------------*//**
+ * Programming services specific status codes:
+ */
+#define MSS_SYS_CHAINING_MISMATCH 1u
+#define MSS_SYS_UNEXPECTED_DATA_RECEIVED 2u
+#define MSS_SYS_INVALID_ENCRYPTION_KEY 3u
+#define MSS_SYS_INVALID_COMPONENT_HEADER 4u
+#define MSS_SYS_BACK_LEVEL_NOT_SATISFIED 5u
+#define MSS_SYS_DSN_BINDING_MISMATCH 7u
+#define MSS_SYS_ILLEGAL_COMPONENT_SEQUENCE 8u
+#define MSS_SYS_INSUFFICIENT_DEV_CAPABILITIES 9u
+#define MSS_SYS_INCORRECT_DEVICE_ID 10u
+#define MSS_SYS_UNSUPPORTED_BITSTREAM_PROT_VER 11u
+#define MSS_SYS_VERIFY_NOT_PERMITTED_ON_BITSTR 12u
+#define MSS_SYS_INVALID_DEVICE_CERTIFICATE 13u
+#define MSS_SYS_ABORT 127u
+#define MSS_SYS_NVM_VERIFY_FAILED 129u
+#define MSS_SYS_DEVICE_SECURITY_PROTECTED 130u
+#define MSS_SYS_PROGRAMMING_MODE_NOT_ENABLED 131u
+#define MSS_SYS_ENVM_PROGRAMMING_OPERATION_FAIL 132u
+#define MSS_SYS_ENVM_VERIFY_OPERATION_FAIL 133u
+#define MSS_SYS_ACCESS_ERROR 134u
+#define MSS_SYS_PUF_ACCESS_ERROR 135u
+#define MSS_SYS_BAD_COMPONENT 136u
+
+/*-------------------------------------------------------------------------*//**
+ These constants are used to specify the event_opcode parameter for the
+ event_handler() function registered with the MSS_SYS_init() function. They are
+ used to specify which asynchronous event is notified to the Cortex-M3 software
+ by the System Controller. Asynchronous events are sent by the System
+ Controller to the Cortex-M3 when some system events of interest occur.
+
+ - FLASH_FREEZE_SHUTDOWN_OPCODE:
+ Indicates that the system is being shutdown as a result of entering the
+ Flash*Freeze mode.
+
+ - FLASH_FREEZE_EXIT_OPCODE:
+ Indicates that the system is exiting Flash*Freeze mode.
+
+ - POR_DIGEST_ERROR_OPCODE
+ Indicates that the MSS has received the POR Digest Check message.
+
+ - TAMPER_ATTEMPT_BOUNDARY_SCAN_OPCODE
+ Indicates that the MSS has received the tamper boundary scan attempt
+ detected.
+
+ - TAMPER_ATTEMPT_BUFFER_ACCESS_OPCODE
+ Indicates that the MSS has received the tamper buffer access attempt
+ detected.
+
+ - TAMPER_ATTEMPT_DEBUG_OPCODE
+ Indicates that the MSS has received the tamper debug attempt detected.
+
+ - TAMPER_ATTEMPT_CHECK_DIGESTS_OPCODE
+ Indicates that the MSS has received the tamper check digest attempt
+ detected.
+
+ - TAMPER_ATTEMPT_ECC_SETUP_INSTRUCTION_OPCODE
+ Indicates that the MSS has received the tamper ECC setup instruction
+ attempt detected.
+
+ - TAMPER_ATTEMPT_FACTORY_PRIVATE_OPCODE
+ Indicates that the MSS has received the tamper factory private attempt
+ detected.
+
+ - TAMPER_ATTEMPT_KEY_VALIDATION_OPCODE
+ Indicates that the MSS has received the tamper key validation attempt
+ detected.
+
+ - TAMPER_ATTEMPT_MISC_OPCODE
+ Indicates that the MSS has received the tamper misc attempt detected.
+
+ - TAMPER_ATTEMPT_PASSCODE_MATCH_OPCODE
+ Indicates that the MSS has received the tamper passcode match attempt
+ detected.
+
+ - TAMPER_ATTEMPT_PASSCODE_SETUP_INSTRUCTION_OPCODE
+ Indicates that the MSS has received the tamper passcode setup instruction
+ attempt detected.
+
+ - TAMPER_ATTEMPT_PROGRAMMING_OPCODE
+ Indicates that the MSS has received the tamper programming attempt detected.
+
+ - TAMPER_ATTEMPT_PUBLIC_INFORMATION_OPCODE
+ Indicates that the MSS has received the tamper public information attempt
+ detected.
+
+ - TAMPER_ATTEMPT_PUF_KEY_MANAGEMENT_OPCODE
+ Indicates that the MSS has received the tamper PUF key management attempt
+ detected.
+
+ - TAMPER_ATTEMPT_UNUSED_OPCODE
+ Indicates that the MSS has received the tamper unused attempt detected.
+
+ - TAMPER_ATTEMPT_USER_JTAG_OPCODE
+ Indicates that the MSS has received the tamper user JTAG attempt detected.
+
+ - TAMPER_ATTEMPT_ZEROIZATION_RECOVERY_OPCODE
+ Indicates that the MSS has received the tamper zeroization recovery
+ attempt detected.
+
+ - TAMPER_FAILURE_BOUNDARY_SCAN_OPCODE
+ Indicates that the MSS has received the tamper boundary scan failure
+ detected.
+
+ - TAMPER_FAILURE_BUFFER_ACCESS_OPCODE
+ Indicates that the MSS has received the tamper buffer access
+ failure detected.
+
+ - TAMPER_FAILURE_DEBUG_OPCODE
+ Indicates that the MSS has received the tamper debug failure detected.
+
+ - TAMPER_FAILURE_CHECK_DIGESTS_OPCODE
+ Indicates that the MSS has received the tamper check digest failure
+ detected.
+
+ - TAMPER_FAILURE_ECC_SETUP_INSTRUCTION_OPCODE
+ Indicates that the MSS has received the tamper ECC setup instruction
+ failure detected.
+
+ - TAMPER_FAILURE_FACTORY_PRIVATE_OPCODE
+ Indicates that the MSS has received the tamper factory private failure
+ detected.
+
+ - TAMPER_FAILURE_KEY_VALIDATION_OPCODE
+ Indicates that the MSS has received the tamper key validation failure
+ detected.
+
+ - TAMPER_FAILURE_MISC_OPCODE
+ Indicates that the MSS has received the tamper misc failure detected.
+
+ - TAMPER_FAILURE_PASSCODE_MATCH_OPCODE
+ Indicates that the MSS has received the tamper passcode match failure
+ detected.
+
+ - TAMPER_FAILURE_PASSCODE_SETUP_INSTRUCTION_OPCODE
+ Indicates that the MSS has received the tamper passcode setup instruction
+ failure detected.
+
+ - TAMPER_FAILURE_PROGRAMMING_OPCODE
+ Indicates that the MSS has received the tamper programming failure detected.
+
+ - TAMPER_FAILURE_PUBLIC_INFORMATION_OPCODE
+ Indicates that the MSS has received the tamper public information failure
+ detected.
+
+ - TAMPER_FAILURE_PUF_KEY_MANAGEMENT_OPCODE
+ Indicates that the MSS has received the tamper PUF key management failure
+ detected.
+
+ - TAMPER_FAILURE_UNUSED_OPCODE
+ Indicates that the MSS has received the tamper unused failure detected.
+
+ - TAMPER_FAILURE_USER_JTAG_OPCODE
+ Indicates that the MSS has received the tamper user jtag failure detected.
+
+ - TAMPER_FAILURE_ZEROIZATION_RECOVERY_OPCODE
+ Indicates that the MSS has received the tamper zeroization recovery
+ failure detected.
+
+ - TAMPER_CLOCK_ERROR_DETECT_OPCODE0
+ Indicates that the MSS has received the tamper clock monitor error detected.
+
+ - TAMPER_HARDWARE_MONITOR_JTAGACTIVE_ERROR_OPCODE
+ Indicates that the MSS has received the tamper jtag active hardware
+ monitor error detected.
+
+ - TAMPER_HARDWARE_MONITOR_LOCKPARITY_ERROR_OPCODE
+ Indicates that the MSS has received the tamper lock parity hardware
+ monitor error detected.
+
+ - TAMPER_HARDWARE_MONITOR_MESHSHORT_ERROR_OPCODE
+ Indicates that the MSS has received the tamper mesh short hardware monitor
+ error detected.
+*/
+#define FLASH_FREEZE_SHUTDOWN_OPCODE 0xE0u
+#define FLASH_FREEZE_EXIT_OPCODE 0xE1u
+#define POR_DIGEST_ERROR_OPCODE 0xF1u
+#define TAMPER_ATTEMPT_BOUNDARY_SCAN_OPCODE 0x80u
+#define TAMPER_ATTEMPT_BUFFER_ACCESS_OPCODE 0x81u
+#define TAMPER_ATTEMPT_DEBUG_OPCODE 0x82u
+#define TAMPER_ATTEMPT_CHECK_DIGESTS_OPCODE 0x83u
+#define TAMPER_ATTEMPT_ECC_SETUP_INSTRUCTION_OPCODE 0x84u
+#define TAMPER_ATTEMPT_FACTORY_PRIVATE_OPCODE 0x85u
+#define TAMPER_ATTEMPT_KEY_VALIDATION_OPCODE 0x86u
+#define TAMPER_ATTEMPT_MISC_OPCODE 0x87u
+#define TAMPER_ATTEMPT_PASSCODE_MATCH_OPCODE 0x88u
+#define TAMPER_ATTEMPT_PASSCODE_SETUP_INSTRUCTION_OPCODE 0x89u
+#define TAMPER_ATTEMPT_PROGRAMMING_OPCODE 0x8Au
+#define TAMPER_ATTEMPT_PUBLIC_INFORMATION_OPCODE 0x8Bu
+#define TAMPER_ATTEMPT_PUF_KEY_MANAGEMENT_OPCODE 0x8Cu
+#define TAMPER_ATTEMPT_UNUSED_OPCODE 0x8Du
+#define TAMPER_ATTEMPT_USER_JTAG_OPCODE 0x8Eu
+#define TAMPER_ATTEMPT_ZEROIZATION_RECOVERY_OPCODE 0x8Fu
+#define TAMPER_FAILURE_BOUNDARY_SCAN_OPCODE 0x90u
+#define TAMPER_FAILURE_BUFFER_ACCESS_OPCODE 0x91u
+#define TAMPER_FAILURE_DEBUG_OPCODE 0x92u
+#define TAMPER_FAILURE_CHECK_DIGESTS_OPCODE 0x93u
+#define TAMPER_FAILURE_ECC_SETUP_INSTRUCTION_OPCODE 0x94u
+#define TAMPER_FAILURE_FACTORY_PRIVATE_OPCODE 0x95u
+#define TAMPER_FAILURE_KEY_VALIDATION_OPCODE 0x96u
+#define TAMPER_FAILURE_MISC_OPCODE 0x97u
+#define TAMPER_FAILURE_PASSCODE_MATCH_OPCODE 0x98u
+#define TAMPER_FAILURE_PASSCODE_SETUP_INSTRUCTION_OPCODE 0x99u
+#define TAMPER_FAILURE_PROGRAMMING_OPCODE 0x9Au
+#define TAMPER_FAILURE_PUBLIC_INFORMATION_OPCODE 0x9Bu
+#define TAMPER_FAILURE_PUF_KEY_MANAGEMENT_OPCODE 0x9Cu
+#define TAMPER_FAILURE_UNUSED_OPCODE 0x9Du
+#define TAMPER_FAILURE_USER_JTAG_OPCODE 0x9Eu
+#define TAMPER_FAILURE_ZEROIZATION_RECOVERY_OPCODE 0x9Fu
+#define TAMPER_CLOCK_ERROR_DETECT_OPCODE 0xA0u
+#define TAMPER_HARDWARE_MONITOR_JTAGACTIVE_ERROR_OPCODE 0xB1u
+#define TAMPER_HARDWARE_MONITOR_LOCKPARITY_ERROR_OPCODE 0xB2u
+#define TAMPER_HARDWARE_MONITOR_MESHSHORT_ERROR_OPCODE 0xB4u
+
+/*-------------------------------------------------------------------------*//**
+ These constants are used to specify the options parameter for the
+ MSS_SYS_flash_freeze() function.
+
+ - MSS_SYS_FPGA_POWER_DOWN:
+ Indicates that the MSS_SYS_flash_freeze() function should request the FPGA
+ fabric to enter Flash*Freeze mode.
+
+ - MSS_SYS_MPLL_POWER_DOWN:
+ Indicates that the MSS_SYS_flash_freeze() function should request the MSS
+ PLL to enter Flash*Freeze mode.
+ */
+#define MSS_SYS_FPGA_POWER_DOWN 0x00u
+#define MSS_SYS_MPLL_POWER_DOWN 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ These constants are used to specify the mode parameter for the
+ MSS_SYS_128aes() and MSS_SYS_256bit_aes() functions.
+
+ - MSS_SYS_ECB_ENCRYPT:
+ Indicates that the cryptography function should perform encryption using
+ the Electronic Codebook (ECB) mode.
+
+ - MSS_SYS_ECB_DECRYPT:
+ Indicates that the cryptography function should perform decryption using
+ the Electronic Codebook (ECB) mode.
+
+ - MSS_SYS_CBC_ENCRYPT:
+ Indicates that the cryptography function should perform encryption using
+ the Cipher-Block Chaining (CBC) mode.
+
+ - MSS_SYS_CBC_DECRYPT:
+ Indicates that the cryptography function should perform decryption using
+ the Cipher-Block Chaining (CBC) mode.
+
+ - MSS_SYS_OFB_ENCRYPT:
+ Indicates that the cryptography function should perform encryption using
+ the Output Feedback (OFB) mode.
+
+ - MSS_SYS_OFB_DECRYPT:
+ Indicates that the cryptography function should perform decryption using
+ the Output Feedback (OFB) mode.
+
+ - MSS_SYS_CTR_ENCRYPT:
+ Indicates that the cryptography function should perform encryption using
+ the Counter (CTR) mode.
+
+ - MSS_SYS_CTR_DECRYPT:
+ Indicates that the cryptography function should perform decryption using
+ the Counter (CTR) mode.
+ */
+#define MSS_SYS_ECB_ENCRYPT 0x00u
+#define MSS_SYS_ECB_DECRYPT 0x80u
+#define MSS_SYS_CBC_ENCRYPT 0x01u
+#define MSS_SYS_CBC_DECRYPT 0x81u
+#define MSS_SYS_OFB_ENCRYPT 0x02u
+#define MSS_SYS_OFB_DECRYPT 0x82u
+#define MSS_SYS_CTR_ENCRYPT 0x03u
+#define MSS_SYS_CTR_DECRYPT 0x83u
+
+/*------------------------------------------------------------------------------
+ These constants are used by non deterministic random bit generator (NDRBG)
+ services to communicate the outcome of a system services request. These status
+ codes are only used by NDRBG services.
+
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR:
+ Indicates that a catastrophic error occurred.
+
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED:
+ Indicates that the maximum number of NDRBG instances has been exceeded.
+ You need to release already instantiated NDRBG instances using the
+ MSS_SYS_ndrbg_uninstantiate() function.
+
+ - MSS_SYS_NRBG_INVALID_HANDLE:
+ Indicates that the handle parameter has an invalid value.
+
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG:
+ Indicates that the requested random number is too long. The requested
+ length is larger than the maximum number of digits that can be generated.
+
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED:
+ Indicates that the supplied additional data length is exceeded.
+ */
+#define MSS_SYS_NRBG_CATASTROPHIC_ERROR 1u
+#define MSS_SYS_NRBG_MAX_INST_EXCEEDED 2u
+#define MSS_SYS_NRBG_INVALID_HANDLE 3u
+#define MSS_SYS_NRBG_GEN_REQ_TOO_BIG 4u
+#define MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED 5u
+
+/*-------------------------------------------------------------------------*//**
+ The sys_serv_isp_complete_handler_t typedef specifies the function prototype
+ of the in-system programming (ISP) completion handler that is passed as a
+ parameter to the MSS_SYS_start_isp() function. The ISP completion handler
+ function must be implemented by the application program and it is called by
+ the System Services driver when an ISP operation initiated by a call to
+ MSS_SYS_start_isp() completes. The ISP completion handler function receives
+ a status parameter indicating the outcome of the ISP operation. Refer to the
+ description of the MSS_SYS_start_isp() function for more details.
+ */
+typedef void (*sys_serv_isp_complete_handler_t)(uint32_t status);
+
+/*-------------------------------------------------------------------------*//**
+ The sys_serv_async_event_handler_t type specifies the function prototype of
+ an asynchronous event handler that can be implemented by the application to
+ handle asynchronous messages from the System Controller. The System
+ Controller sends asynchronous messages to the MSS COMM_BLK when certain
+ events such as Flash*Freeze shutdown, Flash*Freeze exit and power-on-reset
+ (POR) digest check errors are detected during the execution of the following
+ system services:
+ - Flash*Freeze
+ - Power-on-reset (POR) digest check
+ The asynchronous event handler function is registered with the System
+ Services driver through the MSS_SYS_init() function. The driver calls the
+ asynchronous event handler when the MSS COMM_BLK receives an asynchronous message.
+ */
+typedef void (*sys_serv_async_event_handler_t)(uint8_t event_opcode, uint8_t response);
+
+/*-------------------------------------------------------------------------*//**
+ This constant is used as parameter to the MSS_SYS_init() function to indicate
+ that the application code does not supply an asynchronous event handler
+ function.
+ */
+#define MSS_SYS_NO_EVENT_HANDLER ((sys_serv_async_event_handler_t)0)
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_init function initializes the system services communication with
+ the System Controller.
+
+ @param
+ The event_handler parameter specifies an optional asynchronous event
+ handler function. This event handler function is provided by the
+ application. It will be called by the System Services driver whenever an
+ asynchronous event is received from the SmartFusion2 System controller.
+ This event handler is typically used to handle entry and exit of
+ Flash*Freeze mode.
+
+ @return
+ This function does not return a value.
+ */
+void MSS_SYS_init
+(
+ sys_serv_async_event_handler_t event_handler
+);
+
+/*==============================================================================
+ * Device and Design Information Services.
+ */
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_get_serial_number function fetches the 128-bit Device Serial
+ Number (DSN).
+
+ @param p_serial_number
+ The p_serial_number parameter is a pointer to the 16-bytes buffer where the
+ serial number will be written by this system service.
+
+ @return
+ The MSS_SYS_get_serial_number function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_get_serial_number
+(
+ uint8_t * p_serial_number
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_get_user_code functions fetches the 32-bit USERCODE.
+
+ @param p_user_code
+ The p_user_code parameter is a pointer to the 4-bytes buffer where the
+ USERCODE will be written by this system service.
+
+ @return
+ The MSS_SYS_get_user_code function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_get_user_code
+(
+ uint8_t * p_user_code
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_get_design_version function fetches the design version.
+
+ @param p_design_version
+ The p_design_version parameter is a pointer to the 2-bytes buffer where the
+ design version will be written by this system service.
+
+ @return
+ The MSS_SYS_get_design_version function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_get_design_version
+(
+ uint8_t * p_design_version
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_get_device_certificate function fetches the device certificate.
+
+ @param p_device_certificate
+ The p_device_certificate parameter is a pointer to the 512-bytes buffer
+ where the device certificate will be written by this system service.
+
+ @return
+ The MSS_SYS_get_device_certificate function returns one of following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_get_device_certificate
+(
+ uint8_t * p_device_certificate
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_get_secondary_device_certificate function fetches the secondary
+ device certificate. The secondary device certificate is second ECC Key
+ Certificate which is a 640-byte digitally-signed X-509 certificate programmed
+ during manufacturing. This certificate only contains the public key for the
+ ECC key and is otherwise unused by the device.
+
+ @param p_secondary_device_certificate
+ The p_secondary_device_certificate parameter is a pointer to the 640-bytes
+ buffer where the secondary device certificate will be written by this system
+ service.
+
+ @return
+ The MSS_SYS_get_secondary_device_certificate function returns one of
+ following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_get_secondary_device_certificate
+(
+ uint8_t * p_secondary_device_certificate
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_flash_freeze function requests the FPGA to enter the Flash*Freeze
+ mode.
+
+ @param options
+ The options parameter can be used to power down additional parts of
+ SmartFusion2 when the FPGA fabric enters Flash*Freeze mode. This parameter
+ is a bit mask of the following options:
+ - MSS_SYS_FPGA_POWER_DOWN
+ - MSS_SYS_MPLL_POWER_DOWN
+ MSS_SYS_FPGA_POWER_DOWN on its own will only power down the FPGA fabric.
+ MSS_SYS_MPLL_POWER_DOWN specifies that the MSS PLL is powered down during
+ the Flash*Freeze period.
+
+ @return
+ The MSS_SYS_flash_freeze function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+ - MSS_SYS_CLK_DIVISOR_ERROR
+
+ The following example demonstrates how to request the FPGA fabric to enter
+ the Flash*Freeze mode:
+ @code
+ MSS_SYS_flash_freeze(MSS_SYS_FPGA_POWER_DOWN | MSS_SYS_MPLL_POWER_DOWN);
+ @endcode
+ */
+uint8_t MSS_SYS_flash_freeze(uint8_t options);
+
+/*==============================================================================
+ * Cryptographic Services.
+ */
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_128bit_aes function provides access to the SmartFusion2 AES-128
+ cryptography service.
+
+ @param key
+ The key parameter is a pointer to a 16-bytes array containing the key to use
+ for the requested encryption/decryption operation.
+
+ @param iv
+ The iv parameter is a pointer to a 16-bytes array containing the
+ initialization vector that will be used as part of the requested
+ encryption/decryption operation. Its use is different depending on the mode.
+ -----------------------------------------
+ | Mode | Usage |
+ -----------------------------------------
+ | ECB | Ignored. |
+ -----------------------------------------
+ | CBC | Randomization. |
+ -----------------------------------------
+ | OFB | Randomization. |
+ -----------------------------------------
+ | CTR | Used as initial counter value. |
+ -----------------------------------------
+
+ @param nb_blocks
+ The nb_blocks parameter specifies the number of 128-bit blocks of
+ plaintext/ciphertext to be processed by the AES-128 system service.
+
+ @param mode
+ The mode parameter specifies the cipher mode of operation and whether the
+ source text must be encrypted or decrypted. The modes of operation are:
+ - Electronic Codebook (ECB)
+ - Cipher-Block Chaining (CBC)
+ - Output Feedback (OFB)
+ - Counter (CTR)
+ The CTR mode uses the content of the initialization vector as its initial
+ counter value. The counter increment is 2^64.
+ Allowed values for the mode parameter are:
+ - MSS_SYS_ECB_ENCRYPT
+ - MSS_SYS_ECB_DECRYPT
+ - MSS_SYS_CBC_ENCRYPT
+ - MSS_SYS_CBC_DECRYPT
+ - MSS_SYS_OFB_ENCRYPT
+ - MSS_SYS_OFB_DECRYPT
+ - MSS_SYS_CTR_ENCRYPT
+ - MSS_SYS_CTR_DECRYPT
+
+ @param dest_addr
+ The dest_addr parameter is a pointer to the memory buffer where the result
+ of the encryption/decryption operation will be stored.
+
+ @param src_addr
+ The src_addr parameter is a pointer to the memory buffer containing the source
+ plaintext/ciphertext to be encrypted/decrypted.
+
+ @return
+ The MSS_SYS_128bit_aes function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_128bit_aes
+(
+ const uint8_t * key,
+ const uint8_t * iv,
+ uint16_t nb_blocks,
+ uint8_t mode,
+ uint8_t * dest_addr,
+ const uint8_t * src_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_256bit_aes function provides access to the SmartFusion2 AES-256
+ cryptography service.
+
+ @param key
+ The key parameter is a pointer to a 32-bytes array containing the key to use
+ for the requested encryption/decryption operation.
+
+ @param iv
+ The iv parameter is a pointer to a 16-bytes array containing the
+ initialization vector that will be used as part of the requested
+ encryption/decryption operation. Its use is different depending on the mode.
+ -----------------------------------------
+ | Mode | Usage |
+ -----------------------------------------
+ | ECB | Ignored. |
+ -----------------------------------------
+ | CBC | Randomization. |
+ -----------------------------------------
+ | OFB | Randomization. |
+ -----------------------------------------
+ | CTR | Used as initial counter value. |
+ -----------------------------------------
+
+ @param nb_blocks
+ The nb_blocks parameter specifies the number of 128-bit blocks of
+ plaintext/ciphertext requested to be processed by the AES-128 system service.
+
+ @param mode
+ The mode parameter specifies the cipher mode of operation and whether the
+ source text must be encrypted or decrypted. The modes of operation are:
+ - Electronic Codebook (ECB)
+ - Cypher-Block Chaining (CBC)
+ - Output Feedback (OFB)
+ - Counter (CTR)
+ The CTR mode uses the content of the initialization vector as its initial
+ counter value. The counter increment is 2^64.
+ Allowed values for the mode parameter are:
+ - MSS_SYS_ECB_ENCRYPT
+ - MSS_SYS_ECB_DECRYPT
+ - MSS_SYS_CBC_ENCRYPT
+ - MSS_SYS_CBC_DECRYPT
+ - MSS_SYS_OFB_ENCRYPT
+ - MSS_SYS_OFB_DECRYPT
+ - MSS_SYS_CTR_ENCRYPT
+ - MSS_SYS_CTR_DECRYPT
+
+ @param dest_addr
+ The dest_addr parameter is a pointer to the memory buffer where the result
+ of the encryption/decryption operation will be stored.
+
+ @param src_addr
+ The src_addr parameter is a pointer to the memory buffer containing the source
+ plaintext/ciphertext to be encrypted/decrypted.
+
+ @return
+ The MSS_SYS_256bit_aes function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_256bit_aes
+(
+ const uint8_t * key,
+ const uint8_t * iv,
+ uint16_t nb_blocks,
+ uint8_t mode,
+ uint8_t * dest_addr,
+ const uint8_t * src_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_sha256 function provides access to the SmartFusion2 SHA-256
+ cryptography service.
+
+ @param p_data_in
+ The p_data_in parameter is a pointer to the memory location containing the
+ data that will be hashed using the SHA-256 system service.
+
+ @param length
+ The length parameter specifies the length in bits of the data to hash.
+
+ @param result
+ The result parameter is a pointer to a 32 bytes buffer where the hash result
+ will be stored.
+
+ @return
+ The MSS_SYS_sha256 function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_sha256
+(
+ const uint8_t * p_data_in,
+ uint32_t length,
+ uint8_t * result
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_hmac function provides access to the SmartFusion2 HMAC
+ cryptography service. The HMAC system service generates message authentication
+ codes using the SHA-256 hash function.
+
+ @param key
+ The key parameter is a pointer to a 32 bytes array containing the key used
+ to generate the message authentication code.
+
+ @param p_data_in
+ The p_data_in parameter is a pointer to the data to be authenticated.
+
+ @param length
+ The length parameter specifies the number of data bytes for which to generate
+ the authentication code. It is the size of the data pointed to by the
+ p_data_in parameter.
+
+ @param p_result
+ The p_result parameter is a pointer to a 32 bytes buffer where the
+ authentication code generated by the HMAC system service will be stored.
+
+ @return
+ The MSS_SYS_hmac function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_hmac
+(
+ const uint8_t * key,
+ const uint8_t * p_data_in,
+ uint32_t length,
+ uint8_t * p_result
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_key_tree() function provides access to a SHA-256 based key-tree
+ cryptography algorithm. The key-tree service begins with a user-supplied root
+ key and derives an output key based on a 7-bit parameter which can be used to
+ create uniqueness for different applications using the same root key, and a
+ 128-bit path variable. Both the 7-bit input parameter and the 128-bit path
+ variable are assumed to be publicly known. One common use for the output key
+ is as a keyed validator, similar to a message authentication code tag.
+
+ @param p_key
+ The p_key parameter is a pointer to a 32 bytes array containing root key
+ used to generate derived key by Key Tree service and also used to store the
+ derived key.
+
+ @param op_type
+ The op_type parameter specifies the operational parameter to be used to
+ generate the output key.
+
+ @param path
+ The path parameter specifies the 128-bit path to be used to generate the
+ output key.
+
+ @return
+ The MSS_SYS_key_tree function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_key_tree
+(
+ uint8_t* p_key,
+ uint8_t op_type,
+ const uint8_t* path
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_challenge_response function...
+
+ The MSS_SYS_challenge_response() function accept a challenge comprising a
+ 7-bit optype and 128-bit path and return a 256-bit response unique to the
+ given challenge and the device.
+
+ @param p_key
+ The key parameter is a pointer to a 32 bytes array containing 256 bit
+ unique response to the given challenge.
+
+ @param op_type
+ The op_type parameter specifies the operational parameter to be used to
+ generate the unique 256-bits unique response.
+
+ @param path
+ The path parameter specifies the 128-bit path to be used to generate the
+ unique 256-bits unique response.
+
+ @return
+ The MSS_SYS_challenge_response function returns one of following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_challenge_response
+(
+ uint8_t* p_key,
+ uint8_t op_type,
+ const uint8_t* path
+);
+
+/*==============================================================================
+ * Non Deterministic Random Bit Generator Services.
+ */
+ /*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_reset() function is used to reset the
+ non-deterministic random bit generator (NRBG).
+
+ @return
+ The MSS_SYS_nrbg_self_test function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_nrbg_reset(void);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_self_test() function performs a self test of the
+ non-deterministic random bit generator (NRBG).
+
+ @return
+ The MSS_SYS_nrbg_self_test function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_nrbg_self_test(void);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_instantiate() function instantiates a non-deterministic
+ random bit generator (NRBG) instance. A maximum of two concurrent instances
+ are available.
+
+ @param personalization_str
+ The personalization_str parameter is a pointer to a buffer containing a
+ random bit generator personalization string. The personalization string
+ can be up to 128 bytes long.
+
+ @param personalization_str_length
+ The personalization_str_length parameter specifies the byte length of the
+ personalization string pointed to by personalization_str.
+
+ @param p_nrbg_handle
+ The p_nrbg_handle parameter is a pointer to a byte that will contain the
+ handle of the instantiated NRBG if this function call succeeds.
+
+ @return
+ The MSS_SYS_nrbg_instantiate function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_nrbg_instantiate
+(
+ const uint8_t * personalization_str,
+ uint16_t personalization_str_length,
+ uint8_t * p_nrbg_handle
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_generate function generates a random bit sequence up to
+ 128 bytes long.
+
+ @param p_requested_data
+ The p_requested_data parameter is a pointer to the buffer where the requested
+ random data will be stored on completion of this system service.
+
+ @param p_additional_input
+ The p_additional_input parameter is a pointer to the buffer containing
+ additional input data for the random bit generation.
+
+ @param requested_length
+ The requested_length parameter specifies the number of random data bytes
+ requested to be generated. The maximum generated data length is 128 bytes.
+
+ @param additional_input_length
+ The additional_input_length parameter specifies the number of additional
+ input bytes to use in the random data generation.
+
+ @param pr_req
+ The pr_req parameter specifies if prediction resistance is requested.
+
+ @param nrbg_handle
+ The nrbg_handle parameter specifies which non-deterministic random bit
+ generator (NRBG) instance will be used to generate the random data. The
+ value of nrbg_handle is obtained as a result of a previous call to the
+ MSS_SYS_nrbg_instantiate() function.
+
+ @return
+ The MSS_SYS_nrbg_generate function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ */
+uint8_t MSS_SYS_nrbg_generate
+(
+ const uint8_t * p_requested_data,
+ const uint8_t * p_additional_input,
+ uint8_t requested_length,
+ uint8_t additional_input_length,
+ uint8_t pr_req,
+ uint8_t nrbg_handle
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_reseed() function is used to reseed the non-deterministic
+ random bit generator (NRBG) identified by the nrbg_handle parameter.
+
+ @param p_additional_input
+ The additional_input_length parameter specifies the number of additional
+ input bytes used to reseed the NRBG identified by the nrbg_handle parameter.
+
+ @param additional_input_length
+ The additional_input_length parameter specifies the number of additional
+ input bytes used to reseed the NRBG.
+
+ @param nrbg_handle
+ The nrbg_handle parameter specifies which NRBG instance to reseed. The value
+ of nrbg_handle is obtained as a result of a previous call to the
+ MSS_SYS_nrbg_instantiate() function.
+
+ @return
+ The MSS_SYS_nrbg_reseed function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+
+ */
+uint8_t MSS_SYS_nrbg_reseed
+(
+ const uint8_t * p_additional_input,
+ uint8_t additional_input_length,
+ uint8_t nrbg_handle
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_nrbg_uninstantiate() function releases the non-deterministic
+ random bit generator (NRBG) identified by the nrbg_handle parameter.
+
+ @param nrbg_handle
+ The nrbg_handle parameter specifies which NRBG instance will be released.
+ The value of nrbg_handle is obtained as a result of a previous call to the
+ MSS_SYS_nrbg_instantiate() function.
+
+ @return
+ The MSS_SYS_nrbg_uninstantiate function returns one of following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NRBG_CATASTROPHIC_ERROR
+ - MSS_SYS_NRBG_MAX_INST_EXCEEDED
+ - MSS_SYS_NRBG_INVALID_HANDLE
+ - MSS_SYS_NRBG_GEN_REQ_TOO_BIG
+ - MSS_SYS_NRBG_MAX_LENGTH_EXCEEDED
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_nrbg_uninstantiate
+(
+ uint8_t nrbg_handle
+);
+
+/*==============================================================================
+ * Zeroization Services.
+ */
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_zeroize_device() function destroys sensitive information stored on
+ the device. Zeroization system services driver will destroy all user configuration
+ data, user keys, user security settings, NVM, SRAM, FPGA fabric, system
+ controller memory, and crypto-engine registers are erased. The level of
+ information destroyed by this function is configured as part of the hardware
+ flow of the design programmed into the device.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ This function does not return any value.
+*/
+void MSS_SYS_zeroize_device
+(
+ void
+);
+
+/*==============================================================================
+ * Programming Services.
+ */
+
+#define MSS_SYS_PROG_AUTHENTICATE 0u
+#define MSS_SYS_PROG_PROGRAM 1u
+#define MSS_SYS_PROG_VERIFY 2u
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_start_isp() function starts the In-System Programming (ISP)
+ system service which allows the Cortex-M3 processor to directly provide a
+ bitstream for programming the SmartFusion2 device.
+ The ISP system service can perform these services:
+ � Authenticate a programming bitstream
+ � Program the device with a programming bitstream
+ � Verify that a programming bitstream has been correctly programmed
+ The mode parameter specifies the ISP system service to perform. The
+ application must also provide two functions as parameters to the
+ MSS_SYS_start_isp() function. The first function is used by the ISP system
+ service to read the programming bitstream. The second function is used by
+ the ISP system service to notify the application that the ISP system service
+ has completed.
+
+ @param mode
+ The mode parameter specifies ISP service to perform. It can be one of:
+ - MSS_SYS_PROG_AUTHENTICATE
+ - MSS_SYS_PROG_PROGRAM
+ - MSS_SYS_PROG_VERIFY
+
+ @param page_read_handler
+ The page_read_handler parameter is a pointer to a function with the
+ following prototype:
+ uint32_t page_read_handler(uint8 const ** pp_next_page);
+ The page_read_handler function must be implemented by the application
+ program to provide the System Services driver with the address of the
+ next page of programming data to be sent to the System Controller and
+ the number of bytes contained in the next page. Refer to the description
+ of the comblk_page_handler_t type for details of the page_read_handler
+ function�s parameters and return values.
+
+ @param isp_completion_handler
+ The isp_completion_handler parameter is a pointer to a function with the
+ following prototype.
+ void (*sys_serv_isp_complete_handler_t)(uint32_t status);
+ The isp_completion_handler function must be implemented by the application
+ program and it is called by the System Services driver when an ISP
+ operation initiated by a call to MSS_SYS_start_isp() completes.
+
+ The isp_completion_handler function receives one of the following status
+ codes through its status parameter indicating the outcome of the ISP
+ operation:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_CHAINING_MISMATCH
+ - MSS_SYS_UNEXPECTED_DATA_RECEIVED
+ - MSS_SYS_INVALID_ENCRYPTION_KEY
+ - MSS_SYS_INVALID_COMPONENT_HEADER
+ - MSS_SYS_BACK_LEVEL_NOT_SATISFIED
+ - MSS_SYS_DSN_BINDING_MISMATCH
+ - MSS_SYS_ILLEGAL_COMPONENT_SEQUENCE
+ - MSS_SYS_INSUFFICIENT_DEV_CAPABILITIES
+ - MSS_SYS_INCORRECT_DEVICE_ID
+ - MSS_SYS_UNSUPPORTED_BITSTREAM_PROT_VER
+ - MSS_SYS_VERIFY_NOT_PERMITTED_ON_BITSTR
+ - MSS_SYS_ABORT
+ - MSS_SYS_NVM_VERIFY_FAILED
+ - MSS_SYS_DEVICE_SECURITY_PROTECTED
+ - MSS_SYS_PROGRAMMING_MODE_NOT_ENABLED
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+
+ @return
+ This function return status as MSS_SYS_CLK_DIVISOR_ERROR, if fclk, pclk0,
+ pclk1 and clk_fic64 divisor are not equal to each other or set to divide by
+ 32 on 060 device.
+ */
+uint8_t MSS_SYS_start_isp
+(
+ uint8_t mode,
+ comblk_page_handler_t page_read_handler,
+ sys_serv_isp_complete_handler_t isp_completion_handler
+);
+
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_initiate_iap() function invokes the In application programming
+ system service by sending the request to System Controller to reprogram the
+ device using a bitstream present in SPI FLASH connected to MSS SPI-0. The
+ IAP Service is initiated by a call to MSS_SYS_initiate_iap(). The IAP
+ Service can perform these services:
+ - authenticate a programming bitstream
+ - program a bitstream
+ - verify that a programming bitstream has been correctly programmed
+
+ @param mode
+ The mode parameter specifies IAP service to perform. It can be one of:
+ - MSS_SYS_PROG_AUTHENTICATE
+ - MSS_SYS_PROG_PROGRAM
+ - MSS_SYS_PROG_VERIFY
+
+ @param bitstream_spi_addr
+ The bitstream_spi_addr parameter specifies the starting location address of
+ the programmed bitstream present in SPI flash connected to MSS SPI 0.
+ User should copy the programming bitstream into SPI Flash before calling
+ IAP system service.
+
+ @return
+ The MSS_SYS_initiate_iap function will receive one of the following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_CHAINING_MISMATCH
+ - MSS_SYS_UNEXPECTED_DATA_RECEIVED
+ - MSS_SYS_INVALID_ENCRYPTION_KEY
+ - MSS_SYS_INVALID_COMPONENT_HEADER
+ - MSS_SYS_BACK_LEVEL_NOT_SATISFIED
+ - MSS_SYS_DSN_BINDING_MISMATCH
+ - MSS_SYS_ILLEGAL_COMPONENT_SEQUENCE
+ - MSS_SYS_INSUFFICIENT_DEV_CAPABILITIES
+ - MSS_SYS_INCORRECT_DEVICE_ID
+ - MSS_SYS_UNSUPPORTED_BITSTREAM_PROT_VER
+ - MSS_SYS_VERIFY_NOT_PERMITTED_ON_BITSTR
+ - MSS_SYS_INVALID_DEVICE_CERTIFICATE
+ - MSS_SYS_ABORT
+ - MSS_SYS_NVM_VERIFY_FAILED
+ - MSS_SYS_DEVICE_SECURITY_PROTECTED
+ - MSS_SYS_PROGRAMMING_MODE_NOT_ENABLED
+ - MSS_SYS_ENVM_PROGRAMMING_OPERATION_FAIL
+ - MSS_SYS_ENVM_VERIFY_OPERATION_FAIL
+ - MSS_SYS_ACCESS_ERROR
+ - MSS_SYS_PUF_ACCESS_ERROR
+ - MSS_SYS_BAD_COMPONENT
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_CLK_DIVISOR_ERROR
+*/
+uint8_t MSS_SYS_initiate_iap
+(
+ uint8_t mode,
+ uint32_t bitstream_spi_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_check_digest() function is used to recalculate and compare
+ cryptographic digests of selected NVM component(s) � FPGA fabric, eNVM0, and
+ eNVM1 � to those previously computed and saved in NVM.
+ Note: The FPGA fabric will enter the Flash*Freeze state if it is powered up
+ when its digest is checked.
+
+ @param options
+ The options parameter specifies which components' digest will be recalculated
+ and checked. The allowed values for the options parameter are any one of the
+ following bitmask constants or a bitwise OR of more than one:
+ � MSS_SYS_DIGEST_CHECK_FABRIC (bit mask = 0x01)
+ � MSS_SYS_DIGEST_CHECK_ENVM0 (bit mask = 0x02)
+ � MSS_SYS_DIGEST_CHECK_ENVM1 (bit mask = 0x04)
+ � MSS_SYS_DIGEST_CHECK_SYS (bit mask = 0x08)
+ � MSS_SYS_DIGEST_CHECK_ENVMFP (bit mask = 0x10)
+ � MSS_SYS_DIGEST_CHECK_ENVMUP (bit mask = 0x20)
+ NOTE: Private factory eNVM and private user eNVM digest checks are only
+ available on the M2S060 and larger devices.
+ @return
+ The MSS_SYS_check_digest function returns the result of the digest check as
+ an 8-bit unsigned integer. The meaning of the digest check return value is
+ as follows:
+ bit 0: Fabric digest error
+ bit 1: ENVM0 digest error
+ bit 2: ENVM1 digest error
+ bit 3: System Controller ROM digest error
+ bit 4: Private eNVM factory digest error
+ bit 5: Private eNVM user digest error
+ bit 7: Service Disable by user lock.
+ A '1' in one of the above bits indicates a digest mismatch. The return
+ value can be compared to the bitmask constants specified as allowed values
+ for the options parameter to discover which of the NVM components produced
+ a digest check error.
+ On 060 device, the MSS_SYS_check_digest function returns
+ MSS_SYS_CLK_DIVISOR_ERROR, if the the divisor values of fclk, pclk0, pclk1
+ and clk_fic64 divisor are not equal to each other or set to divide by 32.
+ */
+#define MSS_SYS_DIGEST_CHECK_FABRIC 0x01u
+#define MSS_SYS_DIGEST_CHECK_ENVM0 0x02u
+#define MSS_SYS_DIGEST_CHECK_ENVM1 0x04u
+#define MSS_SYS_DIGEST_CHECK_SYS 0x08u
+#define MSS_SYS_DIGEST_CHECK_ENVMFP 0x10u
+#define MSS_SYS_DIGEST_CHECK_ENVMUP 0x20u
+
+#define MSS_SYS_DIGEST_CHECK_SVCDISABLED 0x80u
+
+uint8_t MSS_SYS_check_digest
+(
+ uint8_t options
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_create_activation_code() function is used to create the
+ SRAM-PUF user activation code. This function is typically only used once when
+ enrolling the device into the overall system it operates in. It creates an
+ activation code which will be used to regenerate the SRAM-PUF secret key after
+ each power-up of the SRAM-PUF. The activation code is used to eliminate the
+ randomness of the SRAM-PUF power-up content in order to retrieve the device�s
+ unique PUF secret key.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ The MSS_SYS_puf_create_activation_code() function returns one of the
+ following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_SUBCMD
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_create_activation_code
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_delete_activation_code() function is used to delete the user
+ activation code. This function would typically be used only once when
+ decommissioning the device.
+ Note: This system services is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ The MSS_SYS_puf_delete_activation_code() function returns one of the
+ following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_SUBCMD
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_delete_activation_code
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_get_number_of_keys() function is used to retrieve the number
+ of user keys enrolled with the SRAM-PUF service. The number of enrolled keys
+ is also the key identification number to use for the next key to enroll since
+ keys must be enrolled sequentially and the key numbering starts at zero. Up
+ to 58 keys can be enrolled. Keys number 0 and 1 are used for design security
+ and are not available to the user.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_number_of_user_keys
+ The p_user_key parameter is a pointer to the byte in which the number of
+ keys will be written on successful completion of the system service.
+
+ @return
+ The MSS_SYS_puf_get_number_of_user_keys() function returns one of the
+ following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_INVALID_USER_AC1
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_DRBG_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_get_number_of_keys
+(
+ uint8_t* p_number_of_keys
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_enroll_key() function is used to enroll keys into the
+ SRAM-PUF hardware block. Keys can be either intrinsic keys or extrinsic keys.
+ An intrinsic key�s value is randomly generated by the SRAM-PUF hardware block
+ during key enrollment. An extrinsic key�s value is supplied by the user. A key
+ code is created and stored in the System Controller�s private eNVM during key
+ enrollment. The key code along with the activation code created as part of the
+ call to MSS_SYS_puf_create_activation_code() and the SRAM-PUF start-up value
+ can then be used later to regenerate the enrolled key�s value. Enrolled keys
+ can be later reconstructed and retrieved using the MSS_SYS_puf_fetch_key()
+ function. The value of the key is protected until it is fetched since its
+ actual value is not stored anywhere in the system.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param key_number
+ The key_number parameter specifies the key number that will be used to
+ identify the key in later use after enrollment. The key number will be used
+ to identify which key to retrieve in subsequent calls to function
+ MSS_SYS_puf_fetch_key().
+ Keys must be enrolled sequentially. Therefore, an arbitrary value cannot be
+ used for key_number when enrolling a new key. The value for key_number must
+ be derived from a call to MSS_SYS_puf_get_number_of_keys() to find the
+ number of keys currently enrolled and derive the next key number in the
+ sequence.
+ Note: Valid values for key identification numbers are 2 to 57. Keys number
+ 0 and 1 are used for design security and not available to the user.
+
+ @param key_size
+ The key_size parameter specifies the size of the key to enroll. The key size
+ is a multiple of 64-bit up to 4096-bit.
+
+ @param p_key_value
+ The p_key_value parameter is a pointer to the buffer containing the value of
+ the key to enroll. The buffer pointed to by p_key_value contains the value
+ of the extrinsic key specified by the user.
+ Setting this pointer�s value to zero specifies that an intrinsic key is to
+ be enrolled. In this case, a random value is generated using the SRAM-PUF as
+ the key value.
+
+ @param p_key_location
+ The p_key_location parameter is a pointer to the buffer where the key will
+ be copied when it is fetched through a call to MSS_SYS_puf_fetch_key().
+
+ @return
+ The MSS_SYS_puf_enroll_key() function returns one of the following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_REQUEST_OR_KC
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_INVALID_USER_AC1
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD
+ - MSS_SYS_DRBG_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_enroll_key
+(
+ uint8_t key_number,
+ uint16_t key_size,
+ uint8_t* p_key_value,
+ uint8_t* p_key_location
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_delete_key() function is used to delete a previously enrolled
+ key from the SRAM-PUF.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param key_number
+ The key_number parameter specifies the key number of the key to delete.
+
+ @return
+ The MSS_SYS_puf_delete_key() function returns one of the following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_REQUEST_OR_KC
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_INVALID_USER_AC1
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD
+ - MSS_SYS_DRBG_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_delete_key
+(
+ uint8_t key_number
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_fetch_key() function is used to retrieve a user PUF key from
+ the SRAM-PUF hardware block. The key must have been previously enrolled using
+ the MSS_SYS_puf_enroll_key() function. The key to retrieve is identified
+ through the key number used at key enrollment time. The key value is copied
+ into the buffer location specified at key enrollment time. The location of
+ this buffer is returned through function argument pp_key.
+ The key value is reconstructed based on the SRAM-PUF power-on value, the
+ activation code created when the device was commissioned using the
+ MSS_SYS_puf_create_activation_code() function and the key code stored in the
+ SRAM-PUF hardware block�s private eNVM at key enrollment time. The key value
+ does not exist anywhere in the system until it is retrieved by a call to
+ MSS_SYS_puf_fetch_key(). Care must be taken to destroy the key value returned
+ by MSS_SYS_puf_fetch_key() once it is not required anymore.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param key_number
+ The key_number parameter specifies the key number identifying the user key
+ to fetch. The valid range of key numbers is from 2 to 57.
+
+ @param pp_key
+ The pp_key parameter is a pointer to a pointer to the buffer that will
+ contain the user key value on successful completion of the system service.
+ The pp_key parameter can be set to zero if your application keeps track of
+ the location of the key specified though the call to function
+ MSS_SYS_puf_enroll_key() at key enrollment time.
+
+ @return
+ The MSS_SYS_puf_fetch_key() function returns one of the following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_KEYNUM_OR_ARGUMENT
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_fetch_key
+(
+ uint8_t key_number,
+ uint8_t ** pp_key
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_export_keycodes() function is used to export an encrypted
+ copy of all the key codes used internally by the SRAM-PUF hardware block to
+ reconstruct the enrolled keys. Up to 3894 bytes of data can be exported
+ depending on the number and size of keys enrolled.
+ Keys cannot be fetched any more after calling MSS_SYS_puf_export_keycodes()
+ until a subsequent call to function MSS_SYS_puf_import_keycodes() is made
+ with the exported encrypted key codes.
+ Calling MSS_SYS_puf_export_keycodes() and moving the exported data off chip
+ is similar to removing the enrolled keys from the device. The enrolled keys
+ will only be available again if the exported key codes are imported back into
+ the device.
+ A SmartFusion2 device will only accept imported key codes generated from the
+ last set of enrolled keys on that specific device. This makes the exported
+ key codes data specific to one unique SmartFuson2 device. Key codes cannot
+ be exported from one SmartFusion2 device and imported into another
+ SmartFusion2 device. The exported key codes data is specific to the unique
+ SmartFusion2 device it was exported from.
+ Keys cannot be reconstructed from the exported key codes data since the
+ intrinsic secret of the SRAM-PUF is required to reconstruct the keys from
+ the key codes. Furthermore, the key codes data is also encrypted using a
+ random key generated from the SRAM-PUF thus preventing an attacker from
+ deriving useful information from the exported key codes data.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_keycodes
+ The p_keycodes parameter is a pointer to the buffer where the PUF key codes
+ will be exported.
+
+ @return
+ The MSS_SYS_puf_export_keycodes() function returns one of the following
+ status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_REQUEST_OR_KC
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_INVALID_USER_AC1
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD
+ - MSS_SYS_DRBG_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_puf_export_keycodes
+(
+ uint8_t * p_keycodes
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_import_keycodes() function is used to import a set of PUF
+ key codes that was previously exported using the MSS_SYS_puf_export_keycodes()
+ function. Importing the exported key codes allows the enrolled keys to be
+ regenerated. Enrolled keys cannot be regenerated while the key codes have
+ been exported and not imported back.
+ Importing back the key codes results in all keys being regenerated and copied
+ to the memory locations specified during key enrollment. The content of the
+ buffer holding the imported key codes is modified by function
+ MSS_SYS_puf_import_keycodes() to contain the list of pointers to the
+ locations where the keys have been regenerated. This list starts with the
+ address where key number 2 has been regenerated. The location for keys 0 and
+ 1 are not contained in that list because these keys are used for design
+ security and are not accessible to the user.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_keycodes
+ The p_keycodes parameter is a pointer to the buffer containing the PUF key
+ codes to import.
+
+ @return
+ The MSS_SYS_puf_import_keycodes() function returns one of the following status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_ENVM_ERROR
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_INVALID_REQUEST_OR_KC
+ - MSS_SYS_ENVM_PROGRAM_ERROR
+ - MSS_SYS_INVALID_HASH
+ - MSS_SYS_INVALID_USER_AC1
+ - MSS_SYS_ENVM_VERIFY_ERROR
+ - MSS_SYS_INCORRECT_KEYSIZE_FOR_RENEWING_A_KC
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_USER_KEY_CODE_INVALID_SUBCMD
+ - MSS_SYS_DRBG_ERROR
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+ */
+uint8_t MSS_SYS_puf_import_keycodes
+(
+ uint8_t * p_keycodes
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_fetch_ecc_public_key() function is used to fetch PUF ECC
+ public key from eNVM.
+
+ @param p_puf_public_key
+ The p_puf_public_key parameter is a pointer to buffer where the PUF ECC
+ public key will be stored on successful completion of system service.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @return
+ The MSS_SYS_puf_fetch_ecc_public_key() function returns one of the following
+ status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_NO_VALID_PUBLIC_KEY
+ - MSS_SYS_PRIVATE_ENVM_USER_DIGEST_MISMATCH
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_fetch_ecc_public_key
+(
+ uint8_t* p_puf_public_key
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_puf_get_random_seed() function is used to generate a 256-bit true
+ random number seed using the SmartFusion2 SRAM-PUF.
+
+ @param p_puf_seed
+ The p_puf_seed parameter is a pointer to the buffer where the PUF seed will
+ be stored on successful completion of the system service.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @return
+ The MSS_SYS_puf_get_random_seed() function returns one of the following
+ status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_PUF_ERROR_WHEN_CREATING
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_puf_get_random_seed
+(
+ uint8_t* p_puf_seed
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_ecc_point_multiplication() function provides access to the
+ SmartFusion2 System Controller�s Elliptic Curve Cryptography (ECC) point
+ multiplication system service. The MSS_SYS_ecc_point_multiplication() function
+ computes the point multiplication of a point P on the NIST-384 curve by a
+ scalar value d. The point multiplication results in point Q as follows:
+ d * P = Q
+ The points are defined by their x and y coordinates as follows:
+ P = (x1, y1)
+ Q = (x2, y2)
+ Each x and y coordinate and the scalar d are 384-bit long big-endian numbers.
+ Note: The point at infinity is specified using point x =0, y = 0.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_scalar_d
+ The p_scalar_d parameter is a pointer to a buffer containing the 384-bit
+ scalar d. The scalar d is 384-bit long meaning that p_scalar_d should point
+ to a 96 bytes buffer.
+
+ @param p_point_p
+ The p_point_p parameter is a pointer to a buffer containing the (x1, y1)
+ coordinates of input point P. Each x and y coordinate is 384-bit long
+ meaning that p_point_p should point to a 96 bytes buffer.
+
+ @param p_point_q
+ The p_point_q parameter is a pointer to a buffer where the (x2, y2)
+ coordinates of result Q will be stored. Each x and y coordinate is 384-bit
+ long meaning that p_point_q should point to a 96 bytes buffer.
+
+ @return
+ The MSS_SYS_ecc_point_multiplication function returns one of the following
+ status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_ecc_point_multiplication
+(
+ uint8_t* p_scalar_d,
+ uint8_t* p_point_p,
+ uint8_t* p_point_q
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_ecc_point_addition() function provides access to the SmartFusion2
+ System Controller�s Elliptic Curve Cryptography (ECC) point addition system
+ service. The MSS_SYS_ecc_point_addition() function computes the addition of
+ two points, P and Q, on the NIST P-384 curve. The point addition results in
+ point R as follows:
+ P + Q = R
+ The points are defined by their x and y coordinates as follows:
+ P = (x1, y1)
+ Q = (x2, y2)
+ R = (x3, y3)
+ Each x and y coordinate are 384-bit long big-endian numbers.
+ Note: The point at infinity is specified using point x =0, y = 0.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_point_p
+ The p_point_p parameter is a pointer to a buffer containing the (x1, y1)
+ coordinates of input point P. Each x and y coordinate is 384-bit long
+ meaning that p_point_p should point to a 96 bytes buffer.
+
+ @param p_point_q
+ The p_point_q parameter is a pointer to a buffer containing the (x2, y2)
+ coordinates of input point Q. Each x and y coordinate is 384-bit long
+ meaning that p_point_q should point to a 96 bytes buffer.
+
+ @param p_point_r
+ The p_point_r parameter is a pointer to a buffer where the (x3, y3)
+ coordinates of result R will be stored. Each x and y coordinate is 384-bit
+ long meaning that p_point_r should point to a 96 bytes buffer.
+
+ @return
+ The MSS_SYS_ecc_point_addition() function returns one of the following
+ status codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_MEM_ACCESS_ERROR
+ - MSS_SYS_SERVICE_NOT_LICENSED
+ - MSS_SYS_SERVICE_DISABLED_BY_FACTORY
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+ - MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_ecc_point_addition
+(
+ uint8_t* p_point_p,
+ uint8_t* p_point_q,
+ uint8_t* p_point_r
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_ecc_get_base_point() function provides the value of the base
+ point G for NIST elliptic curve P-384. The value of the base point can then
+ be used to generate a public key by multiplying the base point G with a
+ private key using function MSS_SYS_ecc_point_multiplication().
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param p_point_p
+ The p_point_g parameter is a pointer to a buffer where the coordinate of
+ base point G (xG, yG) for curve P-384 will be stored. Each x and y
+ coordinate is 384-bit long meaning that p_point_g should point to a 96
+ bytes buffer.
+
+ @return
+ This function does not return a value.
+*/
+void MSS_SYS_ecc_get_base_point
+(
+ uint8_t* p_point_g
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_start_clock_monitor() function enables clock monitoring based on
+ user configuration. The system controller will start monitoring the 50MHz
+ clock timing reference for four 1MHz clock cycle. The expected count is 200
+ +/- tolerance. If the clock fall outside the tolerance limits, interrupt will
+ be generated and system controller will send clock monitor tamper detect
+ event through COMBLK. MSS should inform to the application about clock
+ monitoring tamper detect event though call back function.
+ NOTE: Do not enable both start clock monitoring and stop clock monitoring at
+ the same time.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ The MSS_SYS_start_clock_monitor() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_start_clock_monitor
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_stop_clock_monitor() function is used to stop the clock monitoring.
+ System controller will disable 50 MHZ timing clock monitoring and clock
+ monitor tamper detect interrupt.
+ NOTE: Do not enable both start clock monitoring and stop clock monitoring at
+ the same time.
+ NOTE: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ The MSS_SYS_stop_clock_monitor() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_stop_clock_monitor
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_enable_puf_power_down() function is used to instruct the system
+ controller to power down the PUF after each of the following operations:
+ � key fetch
+ � key creation
+ � key import
+ � random seed generation
+ Powering down the PUF after these operations is the default PUF behaviour.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters.
+
+ @return
+ The MSS_SYS_enable_puf_power_down() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_enable_puf_power_down
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_disable_puf_power_down() function is used to retain PUF power
+ after the following operations:
+ � key fetch
+ � key creation
+ � key import
+ � random seed generation
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ The MSS_SYS_disable_puf_power_down() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_disable_puf_power_down
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_clear_lock_parity() function is used to clear the previously set
+ Lock Parity tamper flag. System controller will set this flag on detection of
+ parity error on internal lock data. To clear lock parity flag, use tamper
+ control service with bit 4 of Option set to 1, then the LOCKPARITY tamper flag
+ is cleared provided the hardware conditions are no longer present to raise
+ this flag.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ The MSS_SYS_clear_lock_parity() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_clear_lock_parity
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The MSS_SYS_clear_mesh_short() function is used to clear the previously mesh
+ short tamper flag. System Controller monitors the security flash array for
+ invasive tampering using an active mesh. This mesh is driven by LFSR and the
+ return value is monitored for discrepancies against the expected value generated
+ by the LFSR. When a tamper event is detected the MESHSHORT tamper flag is set,
+ generating a tamper interrupt. To clear mesh short tamper flag, use tamper
+ control service with bit 5 of Options set to 1. The MESHSHORT tamper flag is
+ cleared provided the hardware conditions are no longer present to raise this
+ flag.
+ Note: This system service is only available on large SmartFusion2 devices
+ starting with the M2S060.
+
+ @param
+ This function does not take any parameters
+
+ @return
+ The MSS_SYS_clear_mesh_short() function returns one of the following
+ status codes:
+ � MSS_SYS_SUCCESS
+ � MSS_SYS_UNEXPECTED_ERROR
+*/
+uint8_t MSS_SYS_clear_mesh_short
+(
+ void
+);
+
+/*-------------------------------------------------------------------------*//**
+ The IAP Service requests the System Controller to reprogram the device using
+ a bitstream already programmed into MSS SPI 0. The IAP Service is initiated by
+ a call to MSS_SYS_initiate_IAP(). The IAP Service can:
+ - authenticate a programming bitstream
+ - program a bitstream
+ - verify that a programming bitstream has been correctly programmed
+
+ @param mode
+ The mode parameter specifies IAP service to perform. It can be one of:
+ - MSS_SYS_PROG_AUTHENTICATE
+ - MSS_SYS_PROG_PROGRAM
+ - MSS_SYS_PROG_VERIFY
+
+ @param bitstream_spi_addr
+ The bitstream_spi_addr parameter specifies the address of the programming
+ bitstream within the SPI flash connected to MSS SPI 0.
+
+ @return
+ The MSS_SYS_initiate_IAP function will receive one of the following status
+ codes:
+ - MSS_SYS_SUCCESS
+ - MSS_SYS_CHAINING_MISMATCH
+ - MSS_SYS_UNEXPECTED_DATA_RECEIVED
+ - MSS_SYS_INVALID_ENCRYPTION_KEY
+ - MSS_SYS_INVALID_COMPONENT_HEADER
+ - MSS_SYS_BACK_LEVEL_NOT_SATISFIED
+ - MSS_SYS_DSN_BINDING_MISMATCH
+ - MSS_SYS_ILLEGAL_COMPONENT_SEQUENCE
+ - MSS_SYS_INSUFFICIENT_DEV_CAPABILITIES
+ - MSS_SYS_INCORRECT_DEVICE_ID
+ - MSS_SYS_UNSUPPORTED_BITSTREAM_PROT_VER
+ - MSS_SYS_VERIFY_NOT_PERMITTED_ON_BITSTR
+ - MSS_SYS_INVALID_DEVICE_CERTIFICATE
+ - MSS_SYS_ABORT
+ - MSS_SYS_NVM_VERIFY_FAILED
+ - MSS_SYS_DEVICE_SECURITY_PROTECTED
+ - MSS_SYS_PROGRAMMING_MODE_NOT_ENABLED
+ - MSS_SYS_ENVM_PROGRAMMING_OPERATION_FAIL
+ - MSS_SYS_ENVM_VERIFY_OPERATION_FAIL
+ - MSS_SYS_ACCESS_ERROR
+ - MSS_SYS_PUF_ACCESS_ERROR
+ - MSS_SYS_BAD_COMPONENT
+ - MSS_SYS_SERVICE_DISABLED_BY_USER
+*/
+uint8_t MSS_SYS_initiate_IAP
+(
+ uint8_t mode,
+ uint32_t bitstream_spi_addr
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MSS_SYS_SERVICES_H_ */
diff --git a/bsp/smartfusion2/libraries/mss_uart/mss_uart.c b/bsp/smartfusion2/libraries/mss_uart/mss_uart.c
new file mode 100644
index 0000000000..2d04985fbc
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_uart/mss_uart.c
@@ -0,0 +1,1762 @@
+/*******************************************************************************
+ * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver
+ * implementation.
+ *
+ * SVN $Revision: 5610 $
+ * SVN $Date: 2013-04-05 18:49:30 +0530 (Fri, 05 Apr 2013) $
+ */
+#include "mss_uart.h"
+#include "mss_uart_regs.h"
+#include "../../CMSIS/mss_assert.h"
+#include "../../CMSIS/hw_reg_io.h"
+#include "../../CMSIS/system_m2sxxx.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * Defines
+ */
+#define TX_COMPLETE 0u
+#define TX_FIFO_SIZE 16u
+
+#define FCR_TRIG_LEVEL_MASK 0xC0u
+
+#define IIRF_MASK 0x0Fu
+
+#define INVALID_INTERRUPT 0u
+#define INVALID_IRQ_HANDLER ((mss_uart_irq_handler_t) 0)
+#define NULL_HANDLER ((mss_uart_irq_handler_t) 0)
+
+#define MSS_UART_DATA_READY ((uint8_t) 0x01)
+
+#define SYNC_ASYNC_MODE_MASK (0x7u)
+
+/*******************************************************************************
+ * Possible values for Interrupt Identification Register Field.
+ */
+#define IIRF_MODEM_STATUS 0x00u
+#define IIRF_THRE 0x02u
+#define IIRF_MMI 0x03u
+#define IIRF_RX_DATA 0x04u
+#define IIRF_RX_LINE_STATUS 0x06u
+#define IIRF_DATA_TIMEOUT 0x0Cu
+
+/*******************************************************************************
+ * Receiver error status mask.
+ */
+#define STATUS_ERROR_MASK ( MSS_UART_OVERUN_ERROR | MSS_UART_PARITY_ERROR | \
+ MSS_UART_FRAMING_ERROR | MSS_UART_BREAK_ERROR | \
+ MSS_UART_FIFO_ERROR)
+
+/*******************************************************************************
+ * Cortex-M3 interrupt handler functions implemented as part of the MSS UART
+ * driver.
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void UART0_IRQHandler(void);
+#else
+void UART0_IRQHandler(void);
+#endif
+
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void UART1_IRQHandler(void);
+#else
+void UART1_IRQHandler(void);
+#endif
+
+/*******************************************************************************
+ * Local functions.
+ */
+static void global_init(mss_uart_instance_t * this_uart, uint32_t baud_rate,
+ uint8_t line_config);
+static void MSS_UART_isr(mss_uart_instance_t * this_uart);
+static void default_tx_handler(mss_uart_instance_t * this_uart);
+
+static void config_baud_divisors
+(
+ mss_uart_instance_t * this_uart,
+ uint32_t baudrate
+);
+
+/*******************************************************************************
+ * Instance definitions
+ */
+mss_uart_instance_t g_mss_uart0;
+mss_uart_instance_t g_mss_uart1;
+
+
+/*******************************************************************************
+ * Public Functions
+ *******************************************************************************/
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+)
+{
+ /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
+ * mss_uart_instance_t instances used to identify UART0 and UART1. */
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ /* Perform generic initialization */
+ global_init(this_uart, baud_rate, line_config);
+
+ /* Disable LIN mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
+
+ /* Disable IrDA mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
+
+ /* Disable SmartCard Mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
+
+ /* set default tx handler for automated TX using interrupt in USART mode */
+ this_uart->tx_handler = default_tx_handler;
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void MSS_UART_lin_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+)
+{
+ /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
+ * mss_uart_instance_t instances used to identify UART0 and UART1. */
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ /* Perform generic initialization */
+ global_init(this_uart, baud_rate, line_config);
+
+ /* Enable LIN mode */
+ set_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
+
+ /* Disable IrDA mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
+
+ /* Disable SmartCard Mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_irda_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config,
+ mss_uart_rzi_polarity_t rxpol,
+ mss_uart_rzi_polarity_t txpol,
+ mss_uart_rzi_pulsewidth_t pw
+)
+{
+ /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
+ * mss_uart_instance_t instances used to identify UART0 and UART1. */
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ /* Perform generic initialization */
+ global_init(this_uart, baud_rate, line_config);
+
+ /* Enable LIN mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
+
+ /* Disable IrDA mode */
+ set_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
+ ((rxpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EIRX) :
+ set_bit_reg8(&this_uart->hw_reg->MM1,EIRX));
+
+ ((txpol == MSS_UART_ACTIVE_LOW) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITX) :
+ set_bit_reg8(&this_uart->hw_reg->MM1,EITX));
+
+ ((pw == MSS_UART_3_BY_16) ? clear_bit_reg8(&this_uart->hw_reg->MM1,EITP) :
+ set_bit_reg8(&this_uart->hw_reg->MM1,EITP));
+ /* Disable SmartCard Mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM2, EERR);
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_smartcard_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+)
+{
+ /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
+ * mss_uart_instance_t instances used to identify UART0 and UART1. */
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ /* Perform generic initialization */
+ global_init(this_uart, baud_rate, line_config);
+
+ /* Disable LIN mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM0, ELIN);
+
+ /* Disable IrDA mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM1, EIRD);
+
+ /* Enable SmartCard Mode : Only when data is 8-bit and 2 stop bits*/
+ if( ( MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS) ==
+ (line_config & (MSS_UART_DATA_8_BITS | MSS_UART_TWO_STOP_BITS)))
+ {
+ set_bit_reg8(&this_uart->hw_reg->MM2, EERR);
+ /* Enable single wire half-duplex mode */
+ set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_polled_tx
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+)
+{
+ uint32_t char_idx = 0u;
+ uint32_t size_sent;
+ uint8_t status;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(pbuff != ( (uint8_t *)0));
+ ASSERT(tx_size > 0u);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (pbuff != ((uint8_t *)0)) && (tx_size > 0u))
+ {
+ /* Remain in this loop until the entire input buffer
+ * has been transferred to the UART.
+ */
+ do {
+ /* Read the Line Status Register and update the sticky record */
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+
+ /* Check if TX FIFO is empty. */
+ if(status & MSS_UART_THRE)
+ {
+ uint32_t fill_size = TX_FIFO_SIZE;
+
+ /* Calculate the number of bytes to transmit. */
+ if(tx_size < TX_FIFO_SIZE)
+ {
+ fill_size = tx_size;
+ }
+
+ /* Fill the TX FIFO with the calculated the number of bytes. */
+ for(size_sent = 0u; size_sent < fill_size; ++size_sent)
+ {
+ /* Send next character in the buffer. */
+ this_uart->hw_reg->THR = pbuff[char_idx];
+ char_idx++;
+ }
+
+ /* Calculate the number of untransmitted bytes remaining. */
+ tx_size -= size_sent;
+ }
+ } while(tx_size);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_polled_tx_string
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * p_sz_string
+)
+{
+ uint32_t char_idx = 0u;
+ uint32_t fill_size;
+ uint8_t data_byte;
+ uint8_t status;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(p_sz_string != ((uint8_t *)0));
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (p_sz_string != ((uint8_t *)0)))
+ {
+ /* Get the first data byte from the input buffer */
+ data_byte = p_sz_string[char_idx];
+
+ /* First check for the NULL terminator byte.
+ * Then remain in this loop until the entire string in the input buffer
+ * has been transferred to the UART.
+ */
+ while(0u != data_byte)
+ {
+ /* Wait until TX FIFO is empty. */
+ do {
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+ } while (0u == (status & MSS_UART_THRE));
+
+ /* Send bytes from the input buffer until the TX FIFO is full
+ * or we reach the NULL terminator byte.
+ */
+ fill_size = 0u;
+ while((0u != data_byte) && (fill_size < TX_FIFO_SIZE))
+ {
+ /* Send the data byte */
+ this_uart->hw_reg->THR = data_byte;
+ ++fill_size;
+ char_idx++;
+ /* Get the next data byte from the input buffer */
+ data_byte = p_sz_string[char_idx];
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_irq_tx
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(pbuff != ((uint8_t *)0));
+ ASSERT(tx_size > 0u);
+
+ if((tx_size > 0u) && ( pbuff != ((uint8_t *)0)) &&
+ ((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)))
+ {
+ /*Initialise the transmit info for the UART instance with the arguments.*/
+ this_uart->tx_buffer = pbuff;
+ this_uart->tx_buff_size = tx_size;
+ this_uart->tx_idx = (uint16_t)0;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* assign default handler for data transfer */
+ this_uart->tx_handler = default_tx_handler;
+
+ /* enables TX interrupt */
+ set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+int8_t
+MSS_UART_tx_complete
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ int8_t ret_value = 0;
+ uint8_t status = 0u;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+
+ if((TX_COMPLETE == this_uart->tx_buff_size) &&
+ ((status & MSS_UART_TEMT) != 0u))
+ {
+ ret_value = (int8_t)1;
+ }
+ }
+ return ret_value;
+}
+
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+size_t
+MSS_UART_get_rx
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t * rx_buff,
+ size_t buff_size
+)
+{
+ size_t rx_size = 0u;
+ uint8_t status = 0u;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(rx_buff != ((uint8_t *)0));
+ ASSERT(buff_size > 0u);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (rx_buff != ((uint8_t *)0)) && (buff_size > 0u))
+ {
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+
+ while(((status & MSS_UART_DATA_READY) != 0u) &&
+ (rx_size < buff_size))
+ {
+ rx_buff[rx_size] = this_uart->hw_reg->RBR;
+ ++rx_size;
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+ }
+ }
+ return rx_size;
+}
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_irq
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_t irq_mask
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_IRQ > irq_mask);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_IRQ > irq_mask))
+ {
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* irq_mask encoding: 1- enable
+ * bit 0 - Receive Data Available Interrupt
+ * bit 1 - Transmitter Holding Register Empty Interrupt
+ * bit 2 - Receiver Line Status Interrupt
+ * bit 3 - Modem Status Interrupt
+ */
+ this_uart->hw_reg->IER |= (uint8_t)irq_mask & IIRF_MASK;
+
+ /*
+ * bit 4 - Receiver time-out interrupt
+ * bit 5 - NACK / ERR signal interrupt
+ * bit 6 - PID parity error interrupt
+ * bit 7 - LIN break detection interrupt
+ * bit 8 - LIN Sync detection interrupt
+ */
+ this_uart->hw_reg->IEM |= (uint8_t)(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 4u);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_irq
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_t irq_mask
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* irq_mask encoding: 1 - disable
+ * bit 0 - Receive Data Available Interrupt
+ * bit 1 - Transmitter Holding Register Empty Interrupt
+ * bit 2 - Receiver Line Status Interrupt
+ * bit 3 - Modem Status Interrupt
+ */
+ this_uart->hw_reg->IER &= ((uint8_t)(~((uint32_t)irq_mask & (uint32_t)IIRF_MASK)));
+
+ /*
+ * bit 4 - Receiver time-out interrupt
+ * bit 5 - NACK / ERR signal interrupt
+ * bit 6 - PID parity error interrupt
+ * bit 7 - LIN break detection interrupt
+ * bit 8 - LIN Sync detection interrupt
+ */
+ this_uart->hw_reg->IEM |= (uint8_t)(~(((uint32_t)irq_mask & ~((uint32_t)IIRF_MASK)) >> 8u));
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ if(irq_mask == IIRF_MASK)
+ {
+ /* Disable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_DisableIRQ(this_uart->irqn);
+
+ }
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_rx_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler,
+ mss_uart_rx_trig_level_t trigger_level
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER );
+ ASSERT(trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER) &&
+ (trigger_level < MSS_UART_FIFO_INVALID_TRIG_LEVEL))
+ {
+ this_uart->rx_handler = handler;
+
+ /* Set the receive interrupt trigger level. */
+ this_uart->hw_reg->FCR = (this_uart->hw_reg->FCR &
+ (uint8_t)(~((uint8_t)FCR_TRIG_LEVEL_MASK))) |
+ (uint8_t)trigger_level;
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* Enable receive interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IER,ERBFI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_loopback
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_loopback_t loopback
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_LOOPBACK > loopback);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) ||
+ (MSS_UART_INVALID_LOOPBACK > loopback))
+ {
+ switch(loopback)
+ {
+ case MSS_UART_LOCAL_LOOPBACK_OFF:
+ /* Disable local loopback */
+ clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
+ break;
+
+ case MSS_UART_LOCAL_LOOPBACK_ON:
+ /* Enable local loopback */
+ set_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
+ break;
+
+ case MSS_UART_REMOTE_LOOPBACK_OFF:
+ case MSS_UART_AUTO_ECHO_OFF:
+ /* Disable remote loopback & automatic echo*/
+ this_uart->hw_reg->MCR &= ~RLOOP_MASK;
+ break;
+
+ case MSS_UART_REMOTE_LOOPBACK_ON:
+ /* Enable remote loopback */
+ this_uart->hw_reg->MCR |= (1u << RLOOP);
+ break;
+
+ case MSS_UART_AUTO_ECHO_ON:
+ /* Enable automatic echo */
+ this_uart->hw_reg->MCR |= (1u << ECHO);
+ break;
+
+ case MSS_UART_INVALID_LOOPBACK:
+ /* Fall through to default. */
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART0 interrupt service routine.
+ * UART0_IRQHandler is included within the Cortex-M3 vector table as part of the
+ * Fusion 2 CMSIS.
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void UART0_IRQHandler(void)
+#else
+void UART0_IRQHandler(void)
+#endif
+{
+ MSS_UART_isr(&g_mss_uart0);
+}
+
+/***************************************************************************//**
+ * UART1 interrupt service routine.
+ * UART2_IRQHandler is included within the Cortex-M3 vector table as part of the
+ * Fusion 2 CMSIS.
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void UART1_IRQHandler(void)
+#else
+void UART1_IRQHandler(void)
+#endif
+{
+ MSS_UART_isr(&g_mss_uart1);
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_rxstatus_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->linests_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* Enable receiver line status interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IER,ELSI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_tx_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->tx_handler = handler;
+
+ /* Make TX buffer info invalid */
+ this_uart->tx_buffer = (const uint8_t *)0;
+ this_uart->tx_buff_size = 0u;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* Enable transmitter holding register Empty interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_modemstatus_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->modemsts_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ(this_uart->irqn);
+
+ /* Enable modem status interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IER,EDSSI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+size_t
+MSS_UART_fill_tx_fifo
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ uint8_t status = 0u;
+ size_t size_sent = 0u;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(tx_buffer != ( (uint8_t *)0));
+ 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 == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (tx_buffer != ((uint8_t *)0)) &&
+ (tx_size > 0u))
+ {
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+
+ if(status & MSS_UART_THRE)
+ {
+ uint32_t fill_size = TX_FIFO_SIZE;
+
+ if(tx_size < TX_FIFO_SIZE)
+ {
+ fill_size = tx_size;
+ }
+ /* Fill up FIFO */
+ for(size_sent = 0u; size_sent < fill_size; ++size_sent)
+ {
+
+ /* Send next character in the buffer. */
+ this_uart->hw_reg->THR = tx_buffer[size_sent];
+ }
+ }
+ }
+ return size_sent;
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+uint8_t
+MSS_UART_get_rx_status
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ uint8_t status = MSS_UART_INVALID_PARAM;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /*
+ * Extract UART receive error status.
+ * Bit 1 - Overflow error status
+ * Bit 2 - Parity error status
+ * Bit 3 - Frame error status
+ * Bit 4 - Break interrupt indicator
+ * Bit 7 - FIFO data error status
+ */
+ this_uart->status |= (this_uart->hw_reg->LSR);
+ status = (this_uart->status & STATUS_ERROR_MASK);
+ /* Clear the sticky status after reading */
+ this_uart->status = 0u;
+ }
+ return status;
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+uint8_t
+MSS_UART_get_modem_status
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ uint8_t status = MSS_UART_INVALID_PARAM;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /*
+ * Extract UART modem status and place in lower bits of "status".
+ * Bit 0 - Delta Clear to Send Indicator
+ * Bit 1 - Delta Clear to Receive Indicator
+ * Bit 2 - Trailing edge of Ring Indicator detector
+ * Bit 3 - Delta Data Carrier Detect indicator
+ * Bit 4 - Clear To Send
+ * Bit 5 - Data Set Ready
+ * Bit 6 - Ring Indicator
+ * Bit 7 - Data Carrier Detect
+ */
+ status = this_uart->hw_reg->MSR;
+ }
+ return status;
+}
+
+/***************************************************************************//**
+ * MSS_UART_get_tx_status.
+ * See mss_uart.h for details of how to use this function.
+ */
+uint8_t
+MSS_UART_get_tx_status
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ uint8_t status = MSS_UART_TX_BUSY;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+ /*
+ * Extract the transmit status bits from the UART's Line Status Register.
+ * Bit 5 - Transmitter Holding Register/FIFO Empty (THRE) status. (If = 1, TX FIFO is empty)
+ * Bit 6 - Transmitter Empty (TEMT) status. (If = 1, both TX FIFO and shift register are empty)
+ */
+ status &= (MSS_UART_THRE | MSS_UART_TEMT);
+ }
+ return status;
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_break
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* set break charecter on Tx line */
+ set_bit_reg8(&this_uart->hw_reg->LCR,SB);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_clear_break
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* remove break charecter from Tx line */
+ clear_bit_reg8(&this_uart->hw_reg->LCR,SB);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_pidpei_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->pid_pei_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ( this_uart->irqn );
+
+ /* Enable PID parity error interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IEM,EPID_PEI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_linbreak_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->break_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ( this_uart->irqn );
+
+ /* Enable LIN break detection interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IEM,ELINBI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_linsync_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->sync_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ( this_uart->irqn );
+
+ /* Enable LIN sync detection interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IEM,ELINSI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_nack_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->nack_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ( this_uart->irqn );
+
+ /* Enable LIN sync detection interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IEM,ENACKI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_rx_timeout_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(handler != INVALID_IRQ_HANDLER);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (handler != INVALID_IRQ_HANDLER))
+ {
+ this_uart->rto_handler = handler;
+
+ /* Clear any previously pended interrupts */
+ NVIC_ClearPendingIRQ( this_uart->irqn );
+
+ /* Enable receiver timeout interrupt. */
+ set_bit_reg8(&this_uart->hw_reg->IEM,ERTOI);
+
+ /* Enable UART instance interrupt in Cortex-M3 NVIC. */
+ NVIC_EnableIRQ(this_uart->irqn);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_half_duplex
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* enable single wire half-duplex mode */
+ set_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_half_duplex
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* enable single wire half-duplex mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_rx_endian
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_endian_t endian
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_ENDIAN > endian);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_ENDIAN > endian))
+ {
+ /* Configure MSB first / LSB first for receiver */
+ ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)) :
+ (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX)));
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_tx_endian
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_endian_t endian
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_ENDIAN > endian);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_ENDIAN > endian))
+ {
+ /* Configure MSB first / LSB first for transmitter */
+ ((MSS_UART_LITTLEEND == endian) ? (clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) :
+ (set_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX)) ) ;
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_filter_length
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_filter_length_t length
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_FILTER_LENGTH > length);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_FILTER_LENGTH > length))
+ {
+ /* Configure glitch filter length */
+ this_uart->hw_reg->GFR = (uint8_t)length;
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_afm
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Disable RX FIFO till address flag with correct address is received */
+ set_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_afm
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Enable RX FIFO irrespective of address flag and
+ correct address is received */
+ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_afclear
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Enable address flag clearing */
+ /* Disable RX FIFO till another address flag with
+ correct address is received */
+ set_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_afclear
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Disable address flag clearing */
+ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFC);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_rx_timeout
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t timeout
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Load the receive timeout value */
+ this_uart->hw_reg->RTO = timeout;
+ /*Enable receiver time-out */
+ set_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_rx_timeout
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /*Disable receiver time-out */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_enable_tx_time_guard
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t timeguard
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /* Load the transmitter time guard value */
+ this_uart->hw_reg->TTG = timeguard;
+ /*Enable transmitter time guard */
+ set_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_disable_tx_time_guard
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ /*Disable transmitter time guard */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_address
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t address
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ this_uart->hw_reg->ADR = address;
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_ready_mode
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_ready_mode_t mode
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_READY_MODE > mode);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_READY_MODE > mode ) )
+ {
+ /* Configure mode 0 or mode 1 for TXRDY and RXRDY */
+ ((MSS_UART_READY_MODE0 == mode) ? clear_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) :
+ set_bit_reg8(&this_uart->hw_reg->FCR,RDYMODE) );
+ }
+}
+
+/***************************************************************************//**
+ * Configure baud divisors using fractional baud rate if possible.
+ */
+static void
+config_baud_divisors
+(
+ mss_uart_instance_t * this_uart,
+ uint32_t baudrate
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ uint32_t baud_value;
+ uint32_t baud_value_by_64;
+ uint32_t baud_value_by_128;
+ uint32_t fractional_baud_value;
+ uint32_t pclk_freq;
+
+ this_uart->baudrate = baudrate;
+
+ /* Force the value of the CMSIS global variables holding the various system
+ * clock frequencies to be updated. */
+ SystemCoreClockUpdate();
+ if(this_uart == &g_mss_uart0)
+ {
+ pclk_freq = g_FrequencyPCLK0;
+ }
+ else
+ {
+ pclk_freq = g_FrequencyPCLK1;
+ }
+
+ /*
+ * Compute baud value based on requested baud rate and PCLK frequency.
+ * The baud value is computed using the following equation:
+ * baud_value = PCLK_Frequency / (baud_rate * 16)
+ */
+ baud_value_by_128 = (8u * pclk_freq) / baudrate;
+ baud_value_by_64 = baud_value_by_128 / 2u;
+ baud_value = baud_value_by_64 / 64u;
+ fractional_baud_value = baud_value_by_64 - (baud_value * 64u);
+ fractional_baud_value += (baud_value_by_128 - (baud_value * 128u)) - (fractional_baud_value * 2u);
+
+ /* Assert if integer baud value fits in 16-bit. */
+ ASSERT(baud_value <= UINT16_MAX);
+
+ if(baud_value <= (uint32_t)UINT16_MAX)
+ {
+ if(baud_value > 1u)
+ {
+ /*
+ * Use Frational baud rate divisors
+ */
+ /* set divisor latch */
+ set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
+
+ /* msb of baud value */
+ this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8);
+ /* lsb of baud value */
+ this_uart->hw_reg->DLR = (uint8_t)baud_value;
+
+ /* reset divisor latch */
+ clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
+
+ /* Enable Fractional baud rate */
+ set_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
+
+ /* Load the fractional baud rate register */
+ ASSERT(fractional_baud_value <= (uint32_t)UINT8_MAX);
+ this_uart->hw_reg->DFR = (uint8_t)fractional_baud_value;
+ }
+ else
+ {
+ /*
+ * Do NOT use Frational baud rate divisors.
+ */
+ /* set divisor latch */
+ set_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
+
+ /* msb of baud value */
+ this_uart->hw_reg->DMR = (uint8_t)(baud_value >> 8u);
+ /* lsb of baud value */
+ this_uart->hw_reg->DLR = (uint8_t)baud_value;
+
+ /* reset divisor latch */
+ clear_bit_reg8(&this_uart->hw_reg->LCR,DLAB);
+
+ /* Disable Fractional baud rate */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+void
+MSS_UART_set_usart_mode
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_usart_mode_t mode
+)
+{
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(MSS_UART_INVALID_SYNC_MODE > mode);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (MSS_UART_INVALID_SYNC_MODE > mode))
+ {
+ /* Nothing to do for the baudrate: operates at PCLK / 2 + glitch filter length */
+ /* Clear the ESYN bits 2:0 */
+ this_uart->hw_reg->MM0 &= ~SYNC_ASYNC_MODE_MASK;
+ this_uart->hw_reg->MM0 |= (uint8_t)mode;
+ }
+}
+
+/*******************************************************************************
+ * Local Functions
+ *******************************************************************************/
+/*******************************************************************************
+ * Global initialization for all modes
+ */
+static void global_init
+(
+ mss_uart_instance_t * this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+)
+{
+ /* The driver expects g_mss_uart0 and g_mss_uart1 to be the only
+ * mss_uart_instance_t instances used to identify UART0 and UART1. */
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if(this_uart == &g_mss_uart0)
+ {
+ this_uart->hw_reg = UART0;
+ this_uart->irqn = UART0_IRQn;
+ /* reset UART0 */
+ SYSREG->SOFT_RST_CR |= SYSREG_MMUART0_SOFTRESET_MASK;
+ /* Clear any previously pended UART0 interrupt */
+ NVIC_ClearPendingIRQ(UART0_IRQn);
+ /* Take UART0 out of reset. */
+ SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART0_SOFTRESET_MASK;
+ }
+ else
+ {
+ this_uart->hw_reg = UART1;
+ this_uart->irqn = UART1_IRQn;
+ /* Reset UART1 */
+ SYSREG->SOFT_RST_CR |= SYSREG_MMUART1_SOFTRESET_MASK;
+ /* Clear any previously pended UART1 interrupt */
+ NVIC_ClearPendingIRQ(UART1_IRQn);
+ /* Take UART1 out of reset. */
+ SYSREG->SOFT_RST_CR &= ~SYSREG_MMUART1_SOFTRESET_MASK;
+ }
+
+ /* disable interrupts */
+ this_uart->hw_reg->IER = 0u;
+
+ /* FIFO configuration */
+ this_uart->hw_reg->FCR = (uint8_t)MSS_UART_FIFO_SINGLE_BYTE;
+ /* clear receiver FIFO */
+ set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_RX_FIFO);
+ /* clear transmitter FIFO */
+ set_bit_reg8(&this_uart->hw_reg->FCR,CLEAR_TX_FIFO);
+
+ /* set default READY mode : Mode 0*/
+ /* enable RXRDYN and TXRDYN pins. The earlier FCR write to set the TX FIFO
+ * trigger level inadvertently disabled the FCR_RXRDY_TXRDYN_EN bit. */
+ set_bit_reg8(&this_uart->hw_reg->FCR,RXRDY_TXRDYN_EN);
+
+ /* disable loopback : local * remote */
+ clear_bit_reg8(&this_uart->hw_reg->MCR,LOOP);
+ clear_bit_reg8(&this_uart->hw_reg->MCR,RLOOP);
+
+ /* set default TX endian */
+ clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_TX);
+ /* set default RX endian */
+ clear_bit_reg8(&this_uart->hw_reg->MM1,E_MSB_RX);
+
+ /* default AFM : disabled */
+ clear_bit_reg8(&this_uart->hw_reg->MM2,EAFM);
+
+ /* disable TX time gaurd */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,ETTG);
+
+ /* set default RX timeout */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,ERTO);
+
+ /* disable fractional baud-rate */
+ clear_bit_reg8(&this_uart->hw_reg->MM0,EFBR);
+
+ /* disable single wire mode */
+ clear_bit_reg8(&this_uart->hw_reg->MM2,ESWM);
+
+ /* set filter to minimum value */
+ this_uart->hw_reg->GFR = 0u;
+ /* set default TX time gaurd */
+ this_uart->hw_reg->TTG = 0u;
+ /* set default RX timeout */
+ this_uart->hw_reg->RTO = 0u;
+
+ /*
+ * Configure baud rate divisors. This uses the frational baud rate divisor
+ * where possible to provide the most accurate baud rat possible.
+ */
+ config_baud_divisors(this_uart, baud_rate);
+
+ /* set the line control register (bit length, stop bits, parity) */
+ this_uart->hw_reg->LCR = line_config;
+
+ /* Instance setup */
+ this_uart->baudrate = baud_rate;
+ this_uart->lineconfig = line_config;
+ this_uart->tx_buff_size = TX_COMPLETE;
+ this_uart->tx_buffer = (const uint8_t *)0;
+ this_uart->tx_idx = 0u;
+
+ /* Default handlers for MSS UART interrupts */
+ this_uart->rx_handler = NULL_HANDLER;
+ this_uart->tx_handler = NULL_HANDLER;
+ this_uart->linests_handler = NULL_HANDLER;
+ this_uart->modemsts_handler = NULL_HANDLER;
+ this_uart->rto_handler = NULL_HANDLER;
+ this_uart->nack_handler = NULL_HANDLER;
+ this_uart->pid_pei_handler = NULL_HANDLER;
+ this_uart->break_handler = NULL_HANDLER;
+ this_uart->sync_handler = NULL_HANDLER;
+
+ /* Initialize the sticky status */
+ this_uart->status = 0u;
+}
+
+/***************************************************************************//**
+ * Interrupt service routine triggered by any MSS UART interrupt. This routine
+ * will call the handler function appropriate to the interrupt from the
+ * handlers previously registered with the driver through calls to the
+ * MSS_UART_set_*_handler() functions, or it will call the default_tx_handler()
+ * function in response to transmit interrupts if MSS_UART_irq_tx() is used to
+ * transmit data.
+ */
+static void
+MSS_UART_isr
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ uint8_t iirf;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+
+ if((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1))
+ {
+ iirf = this_uart->hw_reg->IIR & IIRF_MASK;
+
+ switch (iirf)
+ {
+ case IIRF_MODEM_STATUS: /* Modem status interrupt */
+ {
+ ASSERT(NULL_HANDLER != this_uart->modemsts_handler);
+ if(NULL_HANDLER != this_uart->modemsts_handler)
+ {
+ (*(this_uart->modemsts_handler))(this_uart);
+ }
+ }
+ break;
+
+ case IIRF_THRE: /* Transmitter Holding Register Empty */
+ {
+ ASSERT(NULL_HANDLER != this_uart->tx_handler);
+ if(NULL_HANDLER != this_uart->tx_handler)
+ {
+ (*(this_uart->tx_handler))(this_uart);
+ }
+ }
+ break;
+
+ case IIRF_RX_DATA: /* Received Data Available */
+ case IIRF_DATA_TIMEOUT: /* Received Data Timed-out */
+ {
+ ASSERT(NULL_HANDLER != this_uart->rx_handler);
+ if(NULL_HANDLER != this_uart->rx_handler)
+ {
+ (*(this_uart->rx_handler))(this_uart);
+ }
+ }
+ break;
+
+ case IIRF_RX_LINE_STATUS: /* Line Status Interrupt */
+ {
+ ASSERT(NULL_HANDLER != this_uart->linests_handler);
+ if(NULL_HANDLER != this_uart->linests_handler)
+ {
+ (*(this_uart->linests_handler))(this_uart);
+ }
+ }
+ break;
+
+ case IIRF_MMI:
+ {
+ /* Identify multimode interrupts and handle */
+
+ /* Receiver time-out interrupt */
+ if(read_bit_reg8(&this_uart->hw_reg->IIM,ERTOI))
+ {
+ ASSERT(NULL_HANDLER != this_uart->rto_handler);
+ if(NULL_HANDLER != this_uart->rto_handler)
+ {
+ (*(this_uart->rto_handler))(this_uart);
+ }
+ }
+ /* NACK interrupt */
+ if(read_bit_reg8(&this_uart->hw_reg->IIM,ENACKI))
+ {
+ ASSERT(NULL_HANDLER != this_uart->nack_handler);
+ if(NULL_HANDLER != this_uart->nack_handler)
+ {
+ (*(this_uart->nack_handler))(this_uart);
+ }
+ }
+
+ /* PID parity error interrupt */
+ if(read_bit_reg8(&this_uart->hw_reg->IIM,EPID_PEI))
+ {
+ ASSERT(NULL_HANDLER != this_uart->pid_pei_handler);
+ if(NULL_HANDLER != this_uart->pid_pei_handler)
+ {
+ (*(this_uart->pid_pei_handler))(this_uart);
+ }
+ }
+
+ /* LIN break detection interrupt */
+ if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINBI))
+ {
+ ASSERT(NULL_HANDLER != this_uart->break_handler);
+ if(NULL_HANDLER != this_uart->break_handler)
+ {
+ (*(this_uart->break_handler))(this_uart);
+ }
+ }
+
+ /* LIN Sync detection interrupt */
+ if(read_bit_reg8(&this_uart->hw_reg->IIM,ELINSI))
+ {
+ ASSERT(NULL_HANDLER != this_uart->sync_handler);
+ if(NULL_HANDLER != this_uart->sync_handler)
+ {
+ (*(this_uart->sync_handler))(this_uart);
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ ASSERT(INVALID_INTERRUPT);
+ }
+ break;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * See mss_uart.h for details of how to use this function.
+ */
+static void
+default_tx_handler
+(
+ mss_uart_instance_t * this_uart
+)
+{
+ uint8_t status;
+
+ ASSERT((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1));
+ ASSERT(( (uint8_t *)0 ) != this_uart->tx_buffer);
+ ASSERT(0u < this_uart->tx_buff_size);
+
+ if(((this_uart == &g_mss_uart0) || (this_uart == &g_mss_uart1)) &&
+ (((uint8_t *)0 ) != this_uart->tx_buffer) &&
+ (0u < this_uart->tx_buff_size))
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = this_uart->hw_reg->LSR;
+ this_uart->status |= status;
+
+ /*
+ * This function should only be called as a result of a THRE interrupt.
+ * Verify that this is true before proceeding to transmit data.
+ */
+ if(status & MSS_UART_THRE)
+ {
+ uint32_t i;
+ uint32_t fill_size = TX_FIFO_SIZE;
+ uint32_t tx_remain = this_uart->tx_buff_size - this_uart->tx_idx;
+
+ /* Calculate the number of bytes to transmit. */
+ if(tx_remain < TX_FIFO_SIZE)
+ {
+ fill_size = tx_remain;
+ }
+
+ /* Fill the TX FIFO with the calculated the number of bytes. */
+ for(i = 0u; i < fill_size; ++i)
+ {
+ /* Send next character in the buffer. */
+ this_uart->hw_reg->THR = this_uart->tx_buffer[this_uart->tx_idx];
+ ++this_uart->tx_idx;
+ }
+ }
+
+ /* Flag Tx as complete if all data has been pushed into the Tx FIFO. */
+ if(this_uart->tx_idx == this_uart->tx_buff_size)
+ {
+ this_uart->tx_buff_size = TX_COMPLETE;
+ /* disables TX interrupt */
+ clear_bit_reg8(&this_uart->hw_reg->IER,ETBEI);
+ }
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/bsp/smartfusion2/libraries/mss_uart/mss_uart.h b/bsp/smartfusion2/libraries/mss_uart/mss_uart.h
new file mode 100644
index 0000000000..9efa7ed234
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_uart/mss_uart.h
@@ -0,0 +1,2639 @@
+/*******************************************************************************
+ * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SmartFusion2 Microcontroller Subsystem MMUART bare metal software driver
+ * public API.
+ *
+ * SVN $Revision: 5610 $
+ * SVN $Date: 2013-04-05 18:49:30 +0530 (Fri, 05 Apr 2013) $
+ */
+/*=========================================================================*//**
+ @mainpage SmartFusion2 MSS UART Bare Metal Driver.
+ ==============================================================================
+ @section intro_sec Introduction
+ ==============================================================================
+ The SmartFusion2 microcontroller subsystem (MSS) includes two multi-mode UART
+ (MMUART) peripherals for serial communication. This driver provides a set of
+ functions for controlling the MSS MMUARTs 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.
+ Note: MSS UART is synonymous with MSS MMUART in this document.
+
+ ==============================================================================
+ @section hw_dependencies Hardware Flow Dependencies
+ ==============================================================================
+ The configuration of all features of the MSS MMUART peripherals is covered by
+ this driver with the exception of the SmartFusion2 IOMUX configuration.
+ SmartFusion2 allows multiple non-concurrent uses of some external pins through
+ IOMUX configuration. This feature allows optimization of external pin usage by
+ assigning external pins for use by either the microcontroller subsystem or the
+ FPGA fabric. The MSS MMUART serial signals are routed through IOMUXs to the
+ SmartFusion2 device external pins. The MSS MMUART serial signals may also be
+ routed through IOMUXs to the SmartFusion2 FPGA fabric. For more information on
+ IOMUX, refer to the IOMUX section of the SmartFusion2 Microcontroller
+ Subsystem (MSS) User�s Guide.
+ The IOMUXs are configured using the SmartFusion2 MSS configurator tool. You
+ must ensure that the MSS MMUART peripherals are enabled and configured in the
+ SmartFusion2 MSS configurator if you wish to use them. For more information on
+ IOMUXs, refer to the IOMUX section of the SmartFusion2 Microcontroller
+ Subsystem (MSS) User�s Guide.
+ The base address, register addresses and interrupt number assignment for the
+ MSS MMUART peripherals are defined as constants in the SmartFusion2 CMSIS HAL.
+ You must ensure that the latest SmartFusion2 CMSIS HAL is included in the
+ project settings of the software tool chain used to build your project and
+ that it is generated into your project.
+
+ ==============================================================================
+ @section theory_op Theory of Operation
+ ==============================================================================
+ The MSS MMUART driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Polled transmit and receive functions
+ - Interrupt driven transmit and receive functions
+
+ --------------------------------
+ Initialization and Configuration
+ --------------------------------
+ The MSS MMUART supports the following four broad modes of operation:
+ - UART or USART mode
+ - LIN mode
+ - IrDA mode
+ - Smartcard or ISO 7816 mode
+ The MSS MMUART driver provides the MSS_UART_init(), MSS_UART_lin_init(),
+ MSS_UART_irda_init() and MSS_UART_smartcard_init() functions to initialize the
+ MSS MMUARTs for operation in one of these modes. One of these initialization
+ functions must be called before any other MSS MMUART driver functions can be
+ called. The MSS MMUART operating modes are mutually exclusive; therefore only
+ one of the initialization functions must be called. The first parameter of the
+ initialization functions is a pointer to one of two global data structures
+ used to store state information for each MSS MMUART. A pointer to these data
+ structures is also used as the first parameter to many of the driver functions
+ to identify which MSS MMUART will be used by the called function. The names of
+ these two data structures are g_mss_uart0 and g_mss_uart1. Therefore, any call
+ to an MSS MMUART function should be of the form
+ MSS_UART_function_name( &g_mss_uart0, ... ) or
+ MSS_UART_function_name( &g_mss_uart1, ... ).
+
+ UART or USART Mode
+ For the UART or USART modes of operation, the MSS MMUART driver is initialized
+ through a call to the MSS_UART_init() function. This function takes the UART�s
+ configuration as its parameters. The MSS_UART_init() function must be called
+ before any other MSS MMUART driver functions can be called.
+ The MSS_UART_init() function configures the baud rate based on the input baud
+ rate parameter and if possible uses a fractional baud rate for greater
+ precision. This function disables the LIN, IrDA and SmartCard modes.
+
+ LIN mode
+ For the LIN mode of operation, the MSS MMUART driver is initialized through a
+ call to the MSS_UART_lin_init() function. This function takes the LIN node�s
+ configuration as its parameters. The MSS_UART_lin_init() function must be
+ called before any other MSS MMUART driver functions can be called. The
+ MSS_UART_lin_init() function configures the baud rate based on the input baud
+ rate parameter and if possible uses a fractional baud rate for greater
+ precision. This function disables the IrDA and SmartCard modes.
+ The driver also provides the following LIN mode configuration functions:
+ - MSS_UART_set_break()
+ - MSS_UART_clear_break()
+ - MSS_UART_set_pidpei_handler()
+ - MSS_UART_set_linbreak_handler()
+ - MSS_UART_set_linsync_handler()
+ Note: These LIN mode configuration functions can only be called after the
+ MSS_UART_lin_init() function is called.
+
+ IrDA mode
+ For the IrDA mode of operation, the driver is initialized through a call to
+ the MSS_UART_irda_init() function. This function takes the IrDA node�s
+ configuration as its parameters. The MSS_UART_irda_init() function must be
+ called before any other MSS MMUART driver functions can be called. The
+ MSS_UART_irda_init() function configures the baud rate based on the input baud
+ rate parameter and if possible uses a fractional baud rate for greater
+ precision. This function disables the LIN and SmartCard modes.
+
+ Smartcard or ISO 7816 mode
+ For the Smartcard or ISO 7816 mode of operation, the driver is initialized
+ through a call to the MSS_UART_smartcard_init() function. This function takes
+ the smartcard configuration as its parameters. The MSS_UART_smartcard_init()
+ function must be called before any other MSS MMUART driver functions can be
+ called. The MSS_UART_smartcard_init() function configures the baud rate based
+ on the input baud rate parameter and if possible uses a fractional baud rate
+ for greater precision. This function disables the LIN and IrDA modes.
+ The driver also provides the following Smartcard mode configuration functions:
+ - MSS_UART_enable_halfduplex()
+ - MSS_UART_disable_halfduplex()
+ - MSS_UART_set_nack_handler()
+ Note: These Smartcard mode configuration functions can only be called after
+ the MSS_UART_smartcard_init() function is called.
+
+ Common Configuration Functions
+ The driver also provides the configuration functions that can be used with all
+ MSS MMUART operating modes. These common configuration functions are as
+ follows:
+ - MSS_UART_set_rx_endian()
+ - MSS_UART_set_tx_endian()
+ - MSS_UART_enable_afclear()
+ - MSS_UART_disable_afclear()
+ - MSS_UART_enable_rx_timeout()
+ - MSS_UART_disable_rx_timeout()
+ - MSS_UART_enable_tx_time_guard()
+ - MSS_UART_disable_tx_time_guard()
+ - MSS_UART_set_address()
+ - MSS_UART_set_ready_mode()
+ - MSS_UART_set_usart_mode()
+ - MSS_UART_set_filter_length()
+ - MSS_UART_enable_afm()
+ - MSS_UART_disable_afm()
+ Note: These configuration functions can only be called after one of the
+ MSS_UART_init(), MSS_UART_lin_init(), MSS_UART_irda_init() or
+ MSS_UART_smartcard_init() functions is called.
+
+ --------------------------------------
+ Polled Transmit and Receive Operations
+ --------------------------------------
+ The driver can be used to transmit and receive data once initialized.
+ Data is transmitted using the MSS_UART_polled_tx() function. This function is
+ blocking, meaning that it will only return once the data passed to the
+ function has been sent to the MSS MMUART hardware transmitter. Data received
+ by the MSS MMUART hardware receiver can be read by the MSS_UART_get_rx()
+ function.
+ The MSS_UART_polled_tx_string() function is provided to transmit a NULL (�\0�)
+ terminated string in polled mode. This function is blocking, meaning that it
+ will only return once the data passed to the function has been sent to the MSS
+ MMUART hardware transmitter.
+ The MSS_UART_fill_tx_fifo() function fills the MSS MMUART hardware transmit
+ FIFO with data from a buffer passed as a parameter and returns the number of
+ bytes transferred to the FIFO. If the transmit FIFO is not empty when the
+ MSS_UART_fill_tx_fifo() function is called it returns immediately without
+ transferring any data to the FIFO.
+
+ ---------------------------
+ Interrupt Driven Operations
+ ---------------------------
+ The driver can also transmit or receive data under interrupt control, freeing
+ your application to perform other tasks until an interrupt occurs indicating
+ that the driver�s attention is required.
+
+ Interrupt Handlers
+ The MSS MMUART driver supports all types of interrupt triggered by the MSS
+ MMUART. The driver�s internal top level interrupt handler identifies the
+ source of the MSS MMUART interrupt and calls the corresponding lower level
+ handler function that you previously registered with the driver through calls
+ to the MSS_UART_set_rx_handler(), MSS_UART_set_tx_handler(),
+ MSS_UART_set_rxstatus_handler(), and MSS_UART_set_modemstatus_handler()
+ functions. You are responsible for creating these lower level interrupt
+ handlers as part of your application program and registering them with the
+ driver.
+ Note: The SmartFusion2 CMSIS-PAL defines the UART0_IRQHandler() and
+ UART1_IRQHandler() functions (with weak linkage) and assigns them as the
+ interrupt service routines (ISR) for the MSS MMUART interrupt inputs to
+ the Cortex-M3 NVIC. The MSS MMUART driver provides the implementation
+ functions for both of these ISRs from which it calls its own internal
+ top level, interrupt handler function.
+ The MSS_UART_enable_irq() and MSS_UART_disable_irq() functions are used to
+ enable or disable the received line status, received data available/character
+ timeout, transmit holding register empty and modem status interrupts at the
+ MSS MMUART level. The MSS_UART_enable_irq() function also enables the MSS
+ MMUART instance interrupt at the Cortex-M3 level.
+
+ Transmitting Data
+ Interrupt-driven transmit is initiated by a call to MSS_UART_irq_tx(),
+ specifying the block of data to transmit. Your application is then free to
+ perform other tasks and inquire later whether transmit has completed by
+ calling the MSS_UART_tx_complete() function. The MSS_UART_irq_tx() function
+ enables the UART�s transmit holding register empty (THRE) interrupt and then,
+ when the interrupt goes active, the driver�s default THRE interrupt handler
+ transfers the data block to the UART until the entire block is transmitted.
+ Note: You can use the MSS_UART_set_tx_handler() function to assign an
+ alternative handler to the THRE interrupt. In this case, you must not
+ use the MSS_UART_irq_tx() function to initiate the transmit, as this
+ will re-assign the driver�s default THRE interrupt handler to the THRE
+ interrupt. Instead, your alternative THRE interrupt handler must include
+ a call to the MSS_UART_fill_tx_fifo() function to transfer the data to
+ the UART.
+
+ Receiving Data
+ Interrupt-driven receive is performed by first calling
+ MSS_UART_set_rx_handler() to register a receive handler function that will be
+ called by the driver whenever receive data is available. You must provide this
+ receive handler function which must include a call to the MSS_UART_get_rx()
+ function to actually read the received data.
+
+ -----------
+ UART Status
+ -----------
+ The function MSS_UART_get_rx_status() is used to read the receiver error
+ status. This function returns the overrun, parity, framing, break, and FIFO
+ error status of the receiver.
+ The function MSS_UART_get_tx_status() is used to read the transmitter status.
+ This function returns the transmit empty (TEMT) and transmit holding register
+ empty (THRE) status of the transmitter.
+ The function MSS_UART_get_modem_status() is used to read the modem status
+ flags. This function returns the current value of the modem status register.
+
+ --------
+ Loopback
+ --------
+ The MSS_UART_set_loopback() function can be used to locally loopback the Tx
+ and Rx lines of a UART. This is not to be confused with the loopback of UART0
+ to UART1, which can be achieved through the microcontroller subsystem�s system
+ registers.
+
+ *//*=========================================================================*/
+#ifndef __MSS_UART_H_
+#define __MSS_UART_H_ 1
+
+#include "../../CMSIS/m2sxxx.h"
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ Baud rates
+ The following definitions are used to specify standard baud rates as a
+ parameter to the MSS_UART_init() function.
+ */
+#define MSS_UART_110_BAUD 110
+#define MSS_UART_300_BAUD 300
+#define MSS_UART_1200_BAUD 1200
+#define MSS_UART_2400_BAUD 2400
+#define MSS_UART_4800_BAUD 4800
+#define MSS_UART_9600_BAUD 9600
+#define MSS_UART_19200_BAUD 19200
+#define MSS_UART_38400_BAUD 38400
+#define MSS_UART_57600_BAUD 57600
+#define MSS_UART_115200_BAUD 115200
+#define MSS_UART_230400_BAUD 230400
+#define MSS_UART_460800_BAUD 460800
+#define MSS_UART_921600_BAUD 921600
+
+/***************************************************************************//**
+ Data Bits Length
+ The following defines are used to build the value of the MSS_UART_init()
+ function line_config parameter.
+ */
+#define MSS_UART_DATA_5_BITS ( (uint8_t) 0x00 )
+#define MSS_UART_DATA_6_BITS ( (uint8_t) 0x01 )
+#define MSS_UART_DATA_7_BITS ( (uint8_t) 0x02 )
+#define MSS_UART_DATA_8_BITS ( (uint8_t) 0x03 )
+
+/***************************************************************************//**
+ Parity
+ The following defines are used to build the value of the MSS_UART_init()
+ function line_config parameter.
+ */
+#define MSS_UART_NO_PARITY ( (uint8_t) 0x00 )
+#define MSS_UART_ODD_PARITY ( (uint8_t) 0x08 )
+#define MSS_UART_EVEN_PARITY ( (uint8_t) 0x18 )
+#define MSS_UART_STICK_PARITY_0 ( (uint8_t) 0x38 )
+#define MSS_UART_STICK_PARITY_1 ( (uint8_t) 0x28 )
+
+/***************************************************************************//**
+ Number of Stop Bits
+ The following defines are used to build the value of the MSS_UART_init()
+ function line_config parameter.
+ */
+#define MSS_UART_ONE_STOP_BIT ( (uint8_t) 0x00 )
+#define MSS_UART_ONEHALF_STOP_BIT ( (uint8_t) 0x04 )
+#define MSS_UART_TWO_STOP_BITS ( (uint8_t) 0x04 )
+
+/***************************************************************************//**
+ Receiver Error Status
+ The following defines are used to determine the UART receiver error type.
+ These bit mask constants are used with the return value of the
+ MSS_UART_get_rx_status() function to find out if any errors occurred while
+ receiving data.
+ */
+#define MSS_UART_INVALID_PARAM ( (uint8_t)0xFF )
+#define MSS_UART_NO_ERROR ( (uint8_t)0x00 )
+#define MSS_UART_OVERUN_ERROR ( (uint8_t)0x02 )
+#define MSS_UART_PARITY_ERROR ( (uint8_t)0x04 )
+#define MSS_UART_FRAMING_ERROR ( (uint8_t)0x08 )
+#define MSS_UART_BREAK_ERROR ( (uint8_t)0x10 )
+#define MSS_UART_FIFO_ERROR ( (uint8_t)0x80 )
+
+/***************************************************************************//**
+ Transmitter Status
+ The following definitions are used to determine the UART transmitter status.
+ These bit mask constants are used with the return value of the
+ MSS_UART_get_tx_status() function to find out the status of the transmitter.
+ */
+#define MSS_UART_TX_BUSY ( (uint8_t) 0x00 )
+#define MSS_UART_THRE ( (uint8_t) 0x20 )
+#define MSS_UART_TEMT ( (uint8_t) 0x40 )
+
+/***************************************************************************//**
+ Modem Status
+ The following defines are used to determine the modem status. These bit
+ mask constants are used with the return value of the
+ MSS_UART_get_modem_status() function to find out the modem status of
+ the UART.
+ */
+#define MSS_UART_DCTS ( (uint8_t) 0x01 )
+#define MSS_UART_DDSR ( (uint8_t) 0x02 )
+#define MSS_UART_TERI ( (uint8_t) 0x04 )
+#define MSS_UART_DDCD ( (uint8_t) 0x08 )
+#define MSS_UART_CTS ( (uint8_t) 0x10 )
+#define MSS_UART_DSR ( (uint8_t) 0x20 )
+#define MSS_UART_RI ( (uint8_t) 0x40 )
+#define MSS_UART_DCD ( (uint8_t) 0x80 )
+
+/***************************************************************************//**
+ This typedef specifies the irq_mask parameter for the MSS_UART_enable_irq()
+ and MSS_UART_disable_irq() functions. The driver defines a set of bit masks
+ that are used to build the value of the irq_mask parameter. A bitwise OR of
+ these bit masks is used to enable or disable multiple MSS MMUART interrupts.
+ */
+typedef uint16_t mss_uart_irq_t;
+
+/***************************************************************************//**
+ The following defines specify the interrupt masks to enable and disable MSS
+ MMUART interrupts. They are used to build the value of the irq_mask parameter
+ for the MSS_UART_enable_irq() and MSS_UART_disable_irq() functions. A bitwise
+ OR of these constants is used to enable or disable multiple interrupts.
+ */
+#define MSS_UART_RBF_IRQ 0x001
+#define MSS_UART_TBE_IRQ 0x002
+#define MSS_UART_LS_IRQ 0x004
+#define MSS_UART_MS_IRQ 0x008
+#define MSS_UART_RTO_IRQ 0x010
+#define MSS_UART_NACK_IRQ 0x020
+#define MSS_UART_PIDPE_IRQ 0x040
+#define MSS_UART_LINB_IRQ 0x080
+#define MSS_UART_LINS_IRQ 0x100
+#define MSS_UART_INVALID_IRQ UINT16_MAX
+
+/***************************************************************************//**
+ This enumeration specifies the receiver FIFO trigger level. This is the number
+ of bytes that must be received before the UART generates a receive data
+ available interrupt. It provides the allowed values for the
+ MSS_UART_set_rx_handler() function trigger_level parameter.
+ */
+typedef enum {
+ MSS_UART_FIFO_SINGLE_BYTE = 0x00,
+ MSS_UART_FIFO_FOUR_BYTES = 0x40,
+ MSS_UART_FIFO_EIGHT_BYTES = 0x80,
+ MSS_UART_FIFO_FOURTEEN_BYTES = 0xC0,
+ MSS_UART_FIFO_INVALID_TRIG_LEVEL
+} mss_uart_rx_trig_level_t;
+
+/***************************************************************************//**
+ This enumeration specifies the loopback configuration of the UART. It provides
+ the allowed values for the MSS_UART_set_loopback() function�s loopback
+ parameter. Use MSS_UART_LOCAL_LOOPBACK_ON to set up the UART to locally
+ loopback its Tx and Rx lines. Use MSS_UART_REMOTE_LOOPBACK_ON to set up the
+ UART in remote loopback mode.
+ */
+typedef enum {
+ MSS_UART_LOCAL_LOOPBACK_OFF,
+ MSS_UART_LOCAL_LOOPBACK_ON,
+ MSS_UART_REMOTE_LOOPBACK_OFF,
+ MSS_UART_REMOTE_LOOPBACK_ON,
+ MSS_UART_AUTO_ECHO_OFF,
+ MSS_UART_AUTO_ECHO_ON,
+ MSS_UART_INVALID_LOOPBACK
+} mss_uart_loopback_t;
+
+/***************************************************************************//**
+ IrDA input / output polarity.
+ This enumeration specifies the RZI modem polarity for input and output signals.
+ This is passed as parameters in MSS_UART_irda_init() function.
+ */
+typedef enum {
+ MSS_UART_ACTIVE_LOW = 0u,
+ MSS_UART_ACTIVE_HIGH = 1u,
+ MSS_UART_INVALID_POLARITY
+} mss_uart_rzi_polarity_t;
+
+/***************************************************************************//**
+ IrDA input / output pulse width.
+ This enumeration specifies the RZI modem pulse width for input and output signals.
+ This is passed as parameters in MSS_UART_irda_init() function.
+ */
+typedef enum {
+ MSS_UART_3_BY_16 = 0u,
+ MSS_UART_1_BY_4 = 1u,
+ MSS_UART_INVALID_PW
+} mss_uart_rzi_pulsewidth_t;
+
+/***************************************************************************//**
+ Tx / Rx endianess.
+ This enumeration specifies the MSB first or LSB first for MSS UART transmitter
+ and receiver. The parameter of this type shall be passed in
+ MSS_UART_set_rx_endian()and MSS_UART_set_tx_endian() functions.
+ */
+typedef enum {
+ MSS_UART_LITTLEEND,
+ MSS_UART_BIGEND,
+ MSS_UART_INVALID_ENDIAN
+} mss_uart_endian_t;
+
+/***************************************************************************//**
+ Glitch filter length.
+ This enumeration specifies the glitch filter length. The function
+ MSS_UART_set_filter_length() accepts the parameter of this type.
+ */
+typedef enum {
+ MSS_UART_LEN0 = 0,
+ MSS_UART_LEN1 = 1,
+ MSS_UART_LEN2 = 2,
+ MSS_UART_LEN3 = 3,
+ MSS_UART_LEN4 = 4,
+ MSS_UART_LEN5 = 5,
+ MSS_UART_LEN6 = 6,
+ MSS_UART_LEN7 = 7,
+ MSS_UART_INVALID_FILTER_LENGTH = 8
+} mss_uart_filter_length_t;
+
+/***************************************************************************//**
+ TXRDY and RXRDY mode.
+ This enumeration specifies the TXRDY and RXRDY signal modes. The function
+ MSS_UART_set_ready_mode() accepts the parameter of this type.
+ */
+typedef enum {
+ MSS_UART_READY_MODE0,
+ MSS_UART_READY_MODE1,
+ MSS_UART_INVALID_READY_MODE
+} mss_uart_ready_mode_t;
+
+/***************************************************************************//**
+ USART mode of operation.
+ This enumeration specifies the mode of operation of MSS UART when operating
+ as USART. The function MSS_UART_set_usart_mode() accepts the parameter of this type.
+ */
+typedef enum {
+ MSS_UART_ASYNC_MODE = 0,
+ MSS_UART_SYNC_SLAVE_POS_EDGE_CLK = 1,
+ MSS_UART_SYNC_SLAVE_NEG_EDGE_CLK = 2,
+ MSS_UART_SYNC_MASTER_POS_EDGE_CLK = 3,
+ MSS_UART_SYNC_MASTER_NEG_EDGE_CLK = 4,
+ MSS_UART_INVALID_SYNC_MODE = 5
+} mss_uart_usart_mode_t;
+
+
+/***************************************************************************//**
+ MSS UART instance type.
+ This is type definition for MSS UART instance. You need to create and
+ maintain a record of this type. This holds all data regarding the MSS UART
+ instance
+ */
+typedef struct mss_uart_instance mss_uart_instance_t;
+
+/***************************************************************************//**
+ Interrupt handler prototype.
+ This typedef specifies the function prototype for MSS UART interrupt handlers.
+ All interrupt handlers registered with the MSS UART driver must be of this type.
+ The interrupt handlers are registered with the driver through the
+ MSS_UART_set_rx_handler(), MSS_UART_set_tx_handler(),
+ MSS_UART_set_rxstatus_handler(), and MSS_UART_set_modemstatus_handler()
+ functions.
+ The this_uart parameter is a pointer to either g_mss_uart0 or g_mss_uart1 to
+ identify the MSS UART to associate with the handler function.
+ */
+typedef void (*mss_uart_irq_handler_t)( mss_uart_instance_t * this_uart );
+
+/***************************************************************************//**
+ mss_uart_instance.
+ There is one instance of this structure for each instance of the
+ microcontroller subsystem�s UARTs. Instances of this structure are used to
+ identify a specific UART. A pointer to an initialized instance of the
+ mss_uart_instance_t structure is passed as the first parameter to
+ MSS UART driver functions to identify which UART should perform the
+ requested operation.
+ */
+struct mss_uart_instance{
+ /* CMSIS related defines identifying the UART hardware. */
+ UART_TypeDef * hw_reg; /*!< Pointer to UART registers. */
+ IRQn_Type irqn; /*!< UART's Cortex-M3 NVIC interrupt number. */
+ uint32_t baudrate; /*!< Operating baud rate. */
+ uint8_t lineconfig; /*!< Line configuration parameters. */
+ uint8_t status; /*!< Sticky line status. */
+
+ /* transmit related info (used with interrupt driven transmit): */
+ const uint8_t * tx_buffer; /*!< Pointer to transmit buffer. */
+ uint32_t tx_buff_size; /*!< Transmit buffer size. */
+ uint32_t tx_idx; /*!< Index within transmit buffer of next byte to transmit.*/
+
+ /* line status interrupt handler:*/
+ mss_uart_irq_handler_t linests_handler; /*!< Pointer to user registered line status handler. */
+ /* receive interrupt handler:*/
+ mss_uart_irq_handler_t rx_handler; /*!< Pointer to user registered receiver handler. */
+ /* transmit interrupt handler:*/
+ mss_uart_irq_handler_t tx_handler; /*!< Pointer to user registered transmit handler. */
+ /* modem status interrupt handler:*/
+ mss_uart_irq_handler_t modemsts_handler; /*!< Pointer to user registered modem status handler. */
+ /* receiver timeout interrupt handler */
+ mss_uart_irq_handler_t rto_handler; /*!< Pointer to user registered receiver timeout handler. */
+ /* NACK interrupt handler */
+ mss_uart_irq_handler_t nack_handler; /*!< Pointer to user registered NACK handler. */
+ /* PID parity prror interrup handler */
+ mss_uart_irq_handler_t pid_pei_handler; /*!< Pointer to user registered PID parity error handler. */
+ /* LIN break interrupt handler */
+ mss_uart_irq_handler_t break_handler; /*!< Pointer to user registered LIN break handler. */
+ /* LIN sync detection interrupt handler */
+ mss_uart_irq_handler_t sync_handler; /*!< Pointer to user registered LIN sync dectection handler. */
+};
+
+/***************************************************************************//**
+ This instance of mss_uart_instance_t holds all data related to the operations
+ performed by UART0. The function MSS_UART_init() initializes this structure.
+ A pointer to g_mss_uart0 is passed as the first parameter to MSS UART driver
+ functions to indicate that UART0 should perform the requested operation.
+ */
+extern mss_uart_instance_t g_mss_uart0;
+
+/***************************************************************************//**
+ This instance of mss_uart_instance_t holds all data related to the operations
+ performed by UART1. The function MSS_UART_init() initializes this structure.
+ A pointer to g_mss_uart1 is passed as the first parameter to MSS UART driver
+ functions to indicate that UART1 should perform the requested operation.
+ */
+extern mss_uart_instance_t g_mss_uart1;
+
+/***************************************************************************//**
+ The MSS_UART_init() function initializes and configures one of the SmartFusion2
+ MSS UARTs with the configuration passed as a parameter. The configuration
+ parameters are the baud_rate which is used to generate the baud value and the
+ line_config which is used to specify the line configuration (bit length,
+ stop bits and parity).
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t structure
+ identifying the MSS UART hardware block to be initialized. There are two
+ such data structures, g_mss_uart0 and g_mss_uart1, associated with MSS
+ UART0 and MSS UART1 respectively. This parameter must point to either
+ the g_mss_uart0 or g_mss_uart1 global data structure defined within
+ the UART driver..
+
+ @param baud_rate
+ The baud_rate parameter specifies the baud rate. It can be specified for
+ common baud rates� using the following defines:
+ � MSS_UART_110_BAUD
+ � MSS_UART_300_BAUD
+ � MSS_UART_1200_BAUD
+ � MSS_UART_2400_BAUD
+ � MSS_UART_4800_BAUD
+ � MSS_UART_9600_BAUD
+ � MSS_UART_19200_BAUD
+ � MSS_UART_38400_BAUD
+ � MSS_UART_57600_BAUD
+ � MSS_UART_115200_BAUD
+ � MSS_UART_230400_BAUD
+ � MSS_UART_460800_BAUD
+ � MSS_UART_921600_BAUD
+ Alternatively, any nonstandard baud rate can be specified by simply passing
+ the actual required baud rate as the value for this parameter.
+
+ @param line_config
+ The line_config parameter is the line configuration specifying the bit length,
+ number of stop bits and parity settings. This is a bitwise OR of one value
+ from each of the following groups of allowed values:
+ � One of the following to specify the transmit/receive data bit length:
+ MSS_UART_DATA_5_BITS
+ MSS_UART_DATA_6_BITS,
+ MSS_UART_DATA_7_BITS
+ MSS_UART_DATA_8_BITS
+ � One of the following to specify the parity setting:
+ MSS_UART_NO_PARITY
+ MSS_UART_EVEN_PARITY
+ MSS_UART_ODD_PARITY
+ MSS_UART_STICK_PARITY_0
+ MSS_UART_STICK_PARITY_1
+ � One of the following to specify the number of stop bits:
+ MSS_UART_ONE_STOP_BIT
+ MSS_UART_ONEHALF_STOP_BIT
+ MSS_UART_TWO_STOP_BITS
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ The MSS_UART_lin_init() function is used to initialize the MSS UART for
+ LIN mode of operation. The configuration parameters are the baud_rate which is
+ used to generate the baud value and the line_config which is used to specify
+ the line configuration (bit length, stop bits and parity).
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param baud_rate
+ The baud_rate parameter specifies the baud rate. It can be specified for
+ common baud rates� using the following defines:
+ � MSS_UART_110_BAUD
+ � MSS_UART_300_BAUD
+ � MSS_UART_1200_BAUD
+ � MSS_UART_2400_BAUD
+ � MSS_UART_4800_BAUD
+ � MSS_UART_9600_BAUD
+ � MSS_UART_19200_BAUD
+ � MSS_UART_38400_BAUD
+ � MSS_UART_57600_BAUD
+ � MSS_UART_115200_BAUD
+ � MSS_UART_230400_BAUD
+ � MSS_UART_460800_BAUD
+ � MSS_UART_921600_BAUD
+ Alternatively, any nonstandard baud rate can be specified by simply passing
+ the actual required baud rate as the value for this parameter.
+
+ @param line_config
+ The line_config parameter is the line configuration specifying the bit length,
+ number of stop bits and parity settings. This is a bitwise OR of one value
+ from each of the following groups of allowed values:
+ � One of the following to specify the transmit/receive data bit length:
+ MSS_UART_DATA_5_BITS
+ MSS_UART_DATA_6_BITS,
+ MSS_UART_DATA_7_BITS
+ MSS_UART_DATA_8_BITS
+ � One of the following to specify the parity setting:
+ MSS_UART_NO_PARITY
+ MSS_UART_EVEN_PARITY
+ MSS_UART_ODD_PARITY
+ MSS_UART_STICK_PARITY_0
+ MSS_UART_STICK_PARITY_1
+ � One of the following to specify the number of stop bits:
+ MSS_UART_ONE_STOP_BIT
+ MSS_UART_ONEHALF_STOP_BIT
+ MSS_UART_TWO_STOP_BITS
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ MSS_UART_lin_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_lin_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ The MSS_UART_irda_init() function is used to initialize the MSS UART instance
+ referenced by the parameter this_uart for IrDA mode of operation. This
+ function must be called before calling any other IrDA functionality specific
+ functions.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param baud_rate
+ The baud_rate parameter specifies the baud rate. It can be specified for
+ common baud rates� using the following defines:
+ � MSS_UART_110_BAUD
+ � MSS_UART_300_BAUD
+ � MSS_UART_1200_BAUD
+ � MSS_UART_2400_BAUD
+ � MSS_UART_4800_BAUD
+ � MSS_UART_9600_BAUD
+ � MSS_UART_19200_BAUD
+ � MSS_UART_38400_BAUD
+ � MSS_UART_57600_BAUD
+ � MSS_UART_115200_BAUD
+ � MSS_UART_230400_BAUD
+ � MSS_UART_460800_BAUD
+ � MSS_UART_921600_BAUD
+ Alternatively, any nonstandard baud rate can be specified by simply passing
+ the actual required baud rate as the value for this parameter.
+
+ @param line_config
+ The line_config parameter is the line configuration specifying the bit length,
+ number of stop bits and parity settings. This is a bitwise OR of one value
+ from each of the following groups of allowed values:
+ � One of the following to specify the transmit/receive data bit length:
+ MSS_UART_DATA_5_BITS
+ MSS_UART_DATA_6_BITS,
+ MSS_UART_DATA_7_BITS
+ MSS_UART_DATA_8_BITS
+ � One of the following to specify the parity setting:
+ MSS_UART_NO_PARITY
+ MSS_UART_EVEN_PARITY
+ MSS_UART_ODD_PARITY
+ MSS_UART_STICK_PARITY_0
+ MSS_UART_STICK_PARITY_1
+ � One of the following to specify the number of stop bits:
+ MSS_UART_ONE_STOP_BIT
+ MSS_UART_ONEHALF_STOP_BIT
+ MSS_UART_TWO_STOP_BITS
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_irda_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT,
+ MSS_UART_ACTIVE_LOW,
+ MSS_UART_ACTIVE_LOW,
+ MSS_UART_3_BY_16);
+ @endcode
+ */
+void
+MSS_UART_irda_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config,
+ mss_uart_rzi_polarity_t rxpol,
+ mss_uart_rzi_polarity_t txpol,
+ mss_uart_rzi_pulsewidth_t pw
+);
+
+/***************************************************************************//**
+ The MSS_UART_smartcard_init() function is used to initialize the MSS UART
+ for ISO 7816 (smartcard) mode of operation. The configuration parameters are
+ the baud_rate which is used to generate the baud value and the line_config
+ which is used to specify the line configuration (bit length, stop bits and parity).
+ This function disables all other modes of the MSS UART instance pointed by
+ the parameter this_uart.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param baud_rate
+ The baud_rate parameter specifies the baud rate. It can be specified for
+ common baud rates� using the following defines:
+ � MSS_UART_110_BAUD
+ � MSS_UART_300_BAUD
+ � MSS_UART_1200_BAUD
+ � MSS_UART_2400_BAUD
+ � MSS_UART_4800_BAUD
+ � MSS_UART_9600_BAUD
+ � MSS_UART_19200_BAUD
+ � MSS_UART_38400_BAUD
+ � MSS_UART_57600_BAUD
+ � MSS_UART_115200_BAUD
+ � MSS_UART_230400_BAUD
+ � MSS_UART_460800_BAUD
+ � MSS_UART_921600_BAUD
+ Alternatively, any nonstandard baud rate can be specified by simply passing
+ the actual required baud rate as the value for this parameter.
+
+ @param line_config
+ The line_config parameter is the line configuration specifying the bit length,
+ number of stop bits and parity settings. This is a bitwise OR of one value
+ from each of the following groups of allowed values:
+ � One of the following to specify the transmit/receive data bit length:
+ MSS_UART_DATA_5_BITS
+ MSS_UART_DATA_6_BITS,
+ MSS_UART_DATA_7_BITS
+ MSS_UART_DATA_8_BITS
+ � One of the following to specify the parity setting:
+ MSS_UART_NO_PARITY
+ MSS_UART_EVEN_PARITY
+ MSS_UART_ODD_PARITY
+ MSS_UART_STICK_PARITY_0
+ MSS_UART_STICK_PARITY_1
+ � One of the following to specify the number of stop bits:
+ MSS_UART_ONE_STOP_BIT
+ MSS_UART_ONEHALF_STOP_BIT
+ MSS_UART_TWO_STOP_BITS
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ MSS_UART_smartcard_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_smartcard_init
+(
+ mss_uart_instance_t* this_uart,
+ uint32_t baud_rate,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ The function MSS_UART_polled_tx() is used to transmit data. It transfers the
+ contents of the transmitter data buffer, passed as a function parameter, into
+ the UART�s hardware transmitter FIFO. It returns when the full content of the
+ transmit data buffer has been transferred to the UART�s transmit FIFO. It is
+ safe to release or reuse the memory used as the transmitter data buffer once
+ this function returns.
+
+ Note: This function reads the UART�s line status register (LSR) to poll
+ for the active state of the transmitter holding register empty (THRE) bit
+ before transferring data from the data buffer to the transmitter FIFO. It
+ transfers data to the transmitter FIFO in blocks of 16 bytes or less and
+ allows the FIFO to empty before transferring the next block of data.
+
+ Note: The actual transmission over the serial connection will still be
+ in progress when this function returns. Use the MSS_UART_get_tx_status()
+ function if you need to know when the transmitter is empty.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param pbuff
+ The pbuff parameter is a pointer to a buffer containing the data to
+ be transmitted.
+
+ @param tx_size
+ The tx_size parameter specifies the size, in bytes, of the data to
+ be transmitted.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ uint8_t message[12] = "Hello World";
+
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_polled_tx(&g_mss_uart0, message, sizeof(message));
+
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_polled_tx
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+);
+
+/***************************************************************************//**
+ The function MSS_UART_polled_tx_string() is used to transmit a NULL ('\0')
+ terminated string. It transfers the text string, from the buffer starting at
+ the address pointed to by p_sz_string into the UART�s hardware transmitter
+ FIFO. It returns when the complete string has been transferred to the UART's
+ transmit FIFO. It is safe to release or reuse the memory used as the string
+ buffer once this function returns.
+
+ Note: This function reads the UART�s line status register (LSR) to poll
+ for the active state of the transmitter holding register empty (THRE) bit
+ before transferring data from the data buffer to the transmitter FIFO. It
+ transfers data to the transmitter FIFO in blocks of 16 bytes or less and
+ allows the FIFO to empty before transferring the next block of data.
+
+ Note: The actual transmission over the serial connection will still be
+ in progress when this function returns. Use the MSS_UART_get_tx_status()
+ function if you need to know when the transmitter is empty.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @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
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ uint8_t message[12] = "Hello World";
+
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_polled_tx_string(&g_mss_uart0, message);
+
+ return(0);
+ }
+ @endcode
+
+ */
+void
+MSS_UART_polled_tx_string
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * p_sz_string
+);
+
+
+/***************************************************************************//**
+ The function MSS_UART_irq_tx() is used to initiate an interrupt-driven
+ transmit. It returns immediately after making a note of the transmit buffer
+ location and enabling transmit interrupts both at the UART and Cortex-M3 NVIC
+ level. This function takes a pointer via the pbuff parameter to a memory
+ buffer containing the data to transmit. The memory buffer specified through
+ this pointer must remain allocated and contain the data to transmit until
+ the transmit completion has been detected through calls to function
+ MSS_UART_tx_complete(). The actual transmission over the serial connection
+ is still in progress until calls to the MSS_UART_tx_complete() function
+ indicate transmit completion.
+
+ Note: The MSS_UART_irq_tx() function enables both the transmit holding
+ register empty (THRE) interrupt in the UART and the MSS UART instance
+ interrupt in the Cortex-M3 NVIC as part of its implementation.
+
+ Note: The MSS_UART_irq_tx() function assigns an internal default transmit
+ interrupt handler function to the UART�s THRE interrupt. This interrupt
+ handler overrides any custom interrupt handler that you may have previously
+ registered using the MSS_UART_set_tx_handler() function.
+
+ Note: The MSS_UART_irq_tx() function�s default transmit interrupt
+ handler disables the UART�s THRE interrupt when all of the data has
+ been transferred to the UART's transmit FIFO.
+
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param pbuff
+ The pbuff parameter is a pointer to a buffer containing the data
+ to be transmitted.
+
+ @param tx_size
+ The tx_size parameter specifies the size, in bytes, of the data
+ to be transmitted.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ int main(void)
+ {
+ uint8_t tx_buff[10] = "abcdefghi";
+
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_irq_tx(&g_mss_uart0, tx_buff, sizeof(tx_buff));
+
+ while(0 == MSS_UART_tx_complete(&g_mss_uart0))
+ {
+ ;
+ }
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_irq_tx
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+);
+
+/***************************************************************************//**
+ The MSS_UART_tx_complete() function is used to find out if the interrupt-driven
+ transmit previously initiated through a call to MSS_UART_irq_tx() is complete.
+ This is typically used to find out when it is safe to reuse or release the
+ memory buffer holding transmit data.
+
+ Note: The transfer of all of the data from the memory buffer to the UART�s
+ transmit FIFO and the actual transmission over the serial connection are both
+ complete when a call to the MSS_UART_tx_complete() function indicates transmit
+ completion.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function return a non-zero value if transmit has completed, otherwise
+ it returns zero.
+
+ Example:
+ See the MSS_UART_irq_tx() function for an example that uses the
+ MSS_UART_tx_complete() function.
+ */
+int8_t
+MSS_UART_tx_complete
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_get_rx() function reads the content of the UART receiver�s FIFO
+ and stores it in the receive buffer that is passed via the rx_buff function
+ parameter. It copies either the full contents of the FIFO into the receive
+ buffer, or just enough data from the FIFO to fill the receive buffer,
+ dependent upon the size of the receive buffer passed by the buff_size
+ parameter. The MSS_UART_get_rx() function returns the number of bytes copied
+ into the receive buffer .This function is non-blocking and will return 0
+ immediately if no data has been received.
+
+ Note: The MSS_UART_get_rx() function reads and accumulates the receiver
+ status of the MSS UART 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 MSS_UART_get_rx_status() function returns any receiver errors
+ accumulated during the execution of the MSS_UART_get_rx() function.
+
+ Note: If you need to read the error status for each byte received, set
+ the buff_size to 1 and read the receive line error status for each byte
+ using the MSS_UART_get_rx_status() function.
+ The MSS_UART_get_rx() function can be used in polled mode, where it is called
+ at regular intervals to find out if any data has been received, or in interrupt
+ driven-mode, where it is called as part of a receive handler that is called
+ by the driver as a result of data being received.
+
+ Note: In interrupt driven mode you should call the MSS_UART_get_rx()
+ function as part of the receive handler function that you register with
+ the MSS UART driver through a call to MSS_UART_set_rx_handler().
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param rx_buff
+ The rx_buff parameter is a pointer to a buffer where the received
+ data is copied.
+
+ @param buff_size
+ The buff_size parameter specifies the size of the receive buffer in bytes.
+
+ @return
+ This function returns the number of bytes that were copied into the
+ rx_buff buffer. It returns 0 if no data has been received.
+
+ Polled mode example:
+ @code
+ int main( void )
+ {
+ uint8_t rx_buff[RX_BUFF_SIZE];
+ uint32_t rx_idx = 0;
+
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ while(1)
+ {
+ rx_size = MSS_UART_get_rx(&g_mss_uart0, rx_buff, sizeof(rx_buff));
+ if(rx_size > 0)
+ {
+ process_rx_data(rx_buff, rx_size);
+ }
+ task_a();
+ task_b();
+ }
+ return 0;
+ }
+ @endcode
+
+ Interrupt driven example:
+ @code
+ int main( void )
+ {
+ MSS_UART_init(&g_mss_uart1,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_rx_handler(&g_mss_uart1,
+ uart1_rx_handler,
+ MSS_UART_FIFO_SINGLE_BYTE);
+
+ while(1)
+ {
+ task_a();
+ task_b();
+ }
+ return 0;
+ }
+
+ void uart1_rx_handler(mss_uart_instance_t * this_uart)
+ {
+ uint8_t rx_buff[RX_BUFF_SIZE];
+ uint32_t rx_idx = 0;
+ rx_size = MSS_UART_get_rx(this_uart, rx_buff, sizeof(rx_buff));
+ process_rx_data(rx_buff, rx_size);
+ }
+ @endcode
+ */
+size_t
+MSS_UART_get_rx
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t * rx_buff,
+ size_t buff_size
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_rx_handler() function is used to register a receive handler
+ function that is called by the driver when a UART receive data available (RDA)
+ interrupt occurs. You must create and register the receive handler function
+ to suit your application and it must include a call to the MSS_UART_get_rx()
+ function to actually read the received data.
+
+ Note: The MSS_UART_set_rx_handler() function enables both the RDA
+ interrupt in the UART and the MSS UART instance interrupt in the Cortex-M3
+ NVIC as part
+ of its implementation.
+
+ Note: You can disable the RDA interrupt once the data is received by
+ calling the MSS_UART_disable_irq() function. This is your choice and is
+ dependent upon your application.
+
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is a pointer to a receive interrupt handler function
+ provided by your application that will be called as a result of a UART RDA
+ interrupt. This handler function must be of type mss_uart_irq_handler_t.
+
+ @param trigger_level
+ The trigger_level parameter is the receive FIFO trigger level. This
+ specifies the number of bytes that must be received before the UART
+ triggers an RDA interrupt.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ #define RX_BUFF_SIZE 64
+
+ uint8_t g_rx_buff[RX_BUFF_SIZE];
+
+ void uart0_rx_handler(mss_uart_instance_t * this_uart)
+ {
+ MSS_UART_get_rx(this_uart, &g_rx_buff[g_rx_idx], sizeof(g_rx_buff));
+ }
+
+ int main(void)
+ {
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_rx_handler(&g_mss_uart0,
+ uart0_rx_handler,
+ MSS_UART_FIFO_SINGLE_BYTE);
+
+ while(1)
+ {
+ ;
+ }
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_set_rx_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler,
+ mss_uart_rx_trig_level_t trigger_level
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_loopback() function is used to locally loopback the Tx and
+ Rx lines of a UART. This is not to be confused with the loopback of UART0
+ to UART1, which can be achieved through the microcontroller subsystem�s
+ system registers.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param loopback
+ The loopback parameter indicates whether or not the UART�s transmit
+ and receive lines should be looped back. Allowed values are as follows:
+ - MSS_UART_LOCAL_LOOPBACK_ON
+ - MSS_UART_LOCAL_LOOPBACK_OFF
+ - MSS_UART_REMOTE_LOOPBACK_ON
+ - MSS_UART_REMOTE_LOOPBACK_OFF
+ - MSS_UART_AUTO_ECHO_ON
+ - MSS_UART_AUTO_ECHO_OFF
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_loopback(&g_mss_uart0, MSS_UART_LOCAL_LOOPBACK_OFF);
+ @endcode
+ */
+void
+MSS_UART_set_loopback
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_loopback_t loopback
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_irq() function enables the MSS UART interrupts specified
+ by the irq_mask parameter. The irq_mask parameter identifies the MSS UART
+ interrupts by bit position, as defined in the interrupt enable register (IER)
+ of MSS UART. The MSS UART interrupts and their identifying irq_mask bit
+ positions are as follows:
+ When an irq_mask bit position is set to 1, this function enables the
+ corresponding MSS UART interrupt in the IER register. When an irq_mask bit
+ position is set to 0, the corresponding interrupt�s state remains unchanged in
+ the IER register.
+ Note: The MSS_UART_enable_irq() function also enables the MSS UART instance
+ interrupt in the Cortex-M3 NVIC.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t structure
+ identifying the MSS UART hardware block that will perform the requested
+ function. There are two such data structures, g_mss_uart0 and g_mss_uart1,
+ associated with MSS UART0 and MSS UART1. This parameter must point to either
+ the g_mss_uart0 or g_mss_uart1 global data structure defined within the UART
+ driver.
+
+ @param irq_mask
+ The irq_mask parameter is used to select which of the MSS UART�s interrupts
+ you want to enable. The allowed value for the irq_mask parameter is one of
+ the following constants or a bitwise OR of more than one:
+ - MSS_UART_RBF_IRQ (bit mask = 0x001)
+ - MSS_UART_TBE_IRQ (bit mask = 0x002)
+ - MSS_UART_LS_IRQ (bit mask = 0x004)
+ - MSS_UART_MS_IRQ (bit mask = 0x008)
+ - MSS_UART_RTO_IRQ (bit mask = 0x010)
+ - MSS_UART_NACK_IRQ (bit mask = 0x020)
+ - MSS_UART_PIDPE_IRQ (bit mask = 0x040)
+ - MSS_UART_LINB_IRQ (bit mask = 0x080)
+ - MSS_UART_LINS_IRQ (bit mask = 0x100)
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_enable_irq(&g_mss_uart0,(MSS_UART_RBF_IRQ | MSS_UART_TBE_IRQ));
+ @endcode
+ */
+void
+MSS_UART_enable_irq
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_t irq_mask
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_irq() function disables the MSS UART interrupts specified
+ by the irq_mask parameter. The irq_mask parameter identifies the MSS UART
+ interrupts by bit position, as defined in the interrupt enable register (IER)
+ of MSS UART. The MSS UART interrupts and their identifying bit positions are
+ as follows:
+ When an irq_mask bit position is set to 1, this function disables the
+ corresponding MSS UART interrupt in the IER register. When an irq_mask bit
+ position is set to 0, the corresponding interrupt�s state remains unchanged in
+ the IER register.
+ Note: If you disable all four of the UART�s interrupts, the
+ MSS_UART_disable_irq() function also disables the MSS UART instance
+ interrupt in the Cortex-M3 NVIC.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param irq_mask
+ The irq_mask parameter is used to select which of the MSS UART�s interrupts
+ you want to disable. The allowed value for the irq_mask parameter is one of
+ the following constants or a bitwise OR of more than one:
+ - MSS_UART_RBF_IRQ (bit mask = 0x001)
+ - MSS_UART_TBE_IRQ (bit mask = 0x002)
+ - MSS_UART_LS_IRQ (bit mask = 0x004)
+ - MSS_UART_MS_IRQ (bit mask = 0x008)
+ - MSS_UART_RTO_IRQ (bit mask = 0x010)
+ - MSS_UART_NACK_IRQ (bit mask = 0x020)
+ - MSS_UART_PIDPE_IRQ (bit mask = 0x040)
+ - MSS_UART_LINB_IRQ (bit mask = 0x080)
+ - MSS_UART_LINS_IRQ (bit mask = 0x100)
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_disable_irq(&g_mss_uart0, (MSS_UART_RBF_IRQ | MSS_UART_TBE_IRQ));
+ @endcode
+ */
+void
+MSS_UART_disable_irq
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_t irq_mask
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_pidpei_handler() function is used assign a custom interrupt
+ handler for the PIDPEI (PID parity error interrupt) when the MSS UART is
+ operating in LIN mode.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is the pointer to the custom handler function.
+ This parameter is of type mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_ set_pidpei_handler(&g_mss_uart0, my_pidpei_handler);
+ @endcode
+ */
+void
+MSS_UART_set_pidpei_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_linbreak_handler () function is used assign a custom
+ interrupt handler for the LIN Break detection interrupt when the MSS UART
+ is operating in LIN mode.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is the pointer to the custom handler function.
+ This parameter is of type mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+ Example:
+ @code
+ MSS_UART_set_linbreak_handler(&g_mss_uart0, my_break_handler);
+ @endcode
+ */
+void
+MSS_UART_set_linbreak_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_linsync_handler() function is used assign a custom interrupt
+ handler for the LIN Sync character detection interrupt when the MSS UART
+ is operating in LIN mode.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is the pointer to the custom handler function.
+ This parameter is of type mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+ Example:
+ @code
+ MSS_UART_set_linsync_handler(&g_mss_uart0, my_linsync_handler);
+ @endcode
+ */
+void
+MSS_UART_set_linsync_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_nack_handler() function is used assign a custom interrupt
+ handler for the NACK character detection interrupt when the MSS UART
+ is operating in Smartcard mode.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is the pointer to the custom handler function.
+ This parameter is of type mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+ Example:
+ @code
+ MSS_UART_set_nack_handler(&g_mss_uart0, my_nack_handler);
+ @endcode
+ */
+void
+MSS_UART_set_nack_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_rx_timeout_handler() function is used assign a custom
+ interrupt handler for the receiver timeout interrupt when the MSS UART is
+ operating in mode. It finds application in IrDA mode of operation.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is the pointer to the custom handler function.
+ This parameter is of type mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+ Example:
+ @code
+ MSS_UART_set_rx_timeout_handler(&g_mss_uart0, my_rxtimeout_handler);
+ @endcode
+ */
+void
+MSS_UART_set_rx_timeout_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_rxstatus_handler() function is used to register a receiver
+ status handler function that is called by the driver when a UART receiver
+ line status (RLS) interrupt occurs. You must create and register the handler
+ function to suit your application.
+
+ Note: The MSS_UART_set_rxstatus_handler() function enables both the RLS
+ interrupt in the UART and the MSS UART instance interrupt in the Cortex-M3
+ NVIC as part of its implementation.
+
+ Note: You can disable the RLS interrupt when required by calling the
+ MSS_UART_disable_irq() function. This is your choice and is dependent upon
+ your application.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is a pointer to a receiver line status interrupt
+ handler function provided by your application that will be called as a
+ result of a UART RLS interrupt. This handler function must be of type
+ mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ void uart_rxsts_handler(mss_uart_instance_t * this_uart)
+ {
+ uint8_t status;
+ status = MSS_UART_get_rx_status(this_uart);
+ if(status & MSS_UART_OVERUN_ERROR)
+ {
+ discard_rx_data();
+ }
+ }
+
+ int main(void)
+ {
+ MSS_UART_init( &g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY |
+ MSS_UART_ONE_STOP_BIT );
+
+ MSS_UART_set_rxstatus_handler(&g_mss_uart0, uart_rxsts_handler);
+
+ while(1)
+ {
+ ;
+ }
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_set_rxstatus_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_tx_handler() function is used to register a transmit handler
+ function that is called by the driver when a UART transmit holding register
+ empty (THRE) interrupt occurs. You must create and register the transmit
+ handler function to suit your application. You can use the
+ MSS_UART_fill_tx_fifo() function in your transmit handler function to
+ write data to the transmitter.
+
+ Note: The MSS_UART_set_tx_handler() function enables both the THRE
+ interrupt in the UART and the MSS UART instance interrupt in the Cortex-M3
+ NVIC as part of its implementation.
+
+ Note: You can disable the THRE interrupt when required by calling the
+ MSS_UART_disable_irq() function. This is your choice and is dependent upon
+ your application.
+
+ Note: The MSS_UART_irq_tx() function does not use the transmit handler
+ function that you register with the MSS_UART_set_tx_handler() function.
+ It uses its own internal THRE interrupt handler function that overrides
+ any custom interrupt handler that you register using the
+ MSS_UART_set_tx_handler() function.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is a pointer to a transmit interrupt handler
+ function provided by your application that will be called as a result
+ of a UART THRE interrupt. This handler function must be of type
+ mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ uint8_t * g_tx_buffer;
+ size_t g_tx_size = 0;
+
+ void uart_tx_handler(mss_uart_instance_t * this_uart)
+ {
+ size_t size_in_fifo;
+ size_in_fifo = MSS_UART_fill_tx_fifo(this_uart,
+ (const uint8_t *)g_tx_buffer,
+ g_tx_size);
+
+ if(size_in_fifo == g_tx_size)
+ {
+ g_tx_size = 0;
+ MSS_UART_disable_irq(this_uart, MSS_UART_TBE_IRQ);
+ }
+ else
+ {
+ g_tx_buffer = &g_tx_buffer[size_in_fifo];
+ g_tx_size = g_tx_size - size_in_fifo;
+ }
+ }
+
+ int main(void)
+ {
+ uint8_t message[12] = "Hello world";
+
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY |
+ MSS_UART_ONE_STOP_BIT);
+
+ g_tx_buffer = message;
+ g_tx_size = sizeof(message);
+
+ MSS_UART_set_tx_handler(&g_mss_uart0, uart_tx_handler);
+
+ while(1)
+ {
+ ;
+ }
+ return(0);
+ }
+ @endcode
+ */
+void
+MSS_UART_set_tx_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_modemstatus_handler() function is used to register a modem
+ status handler function that is called by the driver when a UART modem status
+ (MS) interrupt occurs. You must create and register the handler function to
+ suit your application.
+
+ Note: The MSS_UART_set_modemstatus_handler() function enables both the MS
+ interrupt in the UART and the MSS UART instance interrupt in the Cortex-M3 NVIC
+ as part of its implementation.
+
+ Note: You can disable the MS interrupt when required by calling the
+ MSS_UART_disable_irq() function. This is your choice and is dependent
+ upon your application.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param handler
+ The handler parameter is a pointer to a modem status interrupt handler
+ function provided by your application that will be called as a result
+ of a UART MS interrupt. This handler function must be of type
+ mss_uart_irq_handler_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ #include "mss_uart.h"
+
+ void uart_modem_handler(mss_uart_instance_t * this_uart)
+ {
+ uint8_t status;
+ status = MSS_UART_get_modem_status(this_uart);
+ if(status & MSS_UART_CTS)
+ {
+ uart_cts_handler();
+ }
+ }
+
+ int main(void)
+ {
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY |
+ MSS_UART_ONE_STOP_BIT);
+ MSS_UART_set_modemstatus_handler(&g_mss_uart0, uart_modem_handler);
+
+ while(1)
+ {
+ ;
+ }
+ return(0);
+ }
+ @endcode
+ */
+
+void
+MSS_UART_set_modemstatus_handler
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ The MSS_UART_fill_tx_fifo() function fills the UART's hardware transmitter
+ FIFO with the data found in the transmitter buffer that is passed via the
+ tx_buffer function parameter. If the transmitter FIFO is not empty when
+ the function is called, the function returns immediately without transferring
+ any data to the FIFO; otherwise, the function transfers data from the
+ transmitter buffer to the FIFO until it is full or until the complete
+ contents of the transmitter buffer have been copied into the FIFO. The
+ function returns the number of bytes copied into the UART's transmitter FIFO.
+
+ Note: This function reads the UART�s line status register (LSR) to check
+ for the active state of the transmitter holding register empty (THRE) bit
+ before transferring data from the data buffer to the transmitter FIFO. If
+ THRE is 0, the function returns immediately, without transferring any data
+ to the FIFO. If THRE is 1, the function transfers up to 16 bytes of data
+ to the FIFO and then returns.
+
+ Note: The actual transmission over the serial connection will still be
+ in progress when this function returns. Use the MSS_UART_get_tx_status()
+ function if you need to know when the transmitter is empty.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param tx_buffer
+ The tx_buffer parameter is a pointer to a buffer containing the data
+ to be transmitted.
+
+ @param tx_size
+ The tx_size parameter is the size in bytes, of the data to be transmitted.
+
+ @return
+ This function returns the number of bytes copied into the UART's
+ transmitter FIFO.
+
+ Example:
+ @code
+ void send_using_interrupt(uint8_t * pbuff, size_t tx_size)
+ {
+ size_t size_in_fifo;
+ size_in_fifo = MSS_UART_fill_tx_fifo(&g_mss_uart0, pbuff, tx_size);
+ }
+ @endcode
+ */
+size_t
+MSS_UART_fill_tx_fifo
+(
+ mss_uart_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ The MSS_UART_get_rx_status() function returns the receiver error status of the
+ MSS UART instance. It reads both the current error status of the receiver from
+ the UART�s line status register (LSR) and the accumulated error status from
+ preceding calls to the MSS_UART_get_rx() function, and it combines them using
+ a bitwise OR. It returns the cumulative overrun, parity, framing, break and
+ FIFO error status of the receiver, since the previous call to
+ MSS_UART_get_rx_status(), as an 8-bit encoded value.
+
+ Note: The MSS_UART_get_rx() function reads and accumulates the receiver
+ status of the MSS UART instance before reading each byte from the receiver�s
+ data register/FIFO. The driver maintains a sticky record of the cumulative
+ receiver error status, which persists after the MSS_UART_get_rx() function
+ returns. The MSS_UART_get_rx_status() function clears the driver�s sticky
+ receiver error record before returning.
+
+ Note: The driver�s transmit functions also read the line status
+ register (LSR) as part of their implementation. When the driver reads the
+ LSR, the UART clears any active receiver error bits in the LSR. This could
+ result in the driver losing receiver errors. To avoid any loss of receiver
+ errors, the transmit functions also update the driver�s sticky record of the
+ cumulative receiver error status whenever they read the LSR.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function returns the UART�s receiver error status as an 8-bit unsigned
+ integer. The returned value is 0 if no receiver errors occurred. The driver
+ provides a set of bit mask constants that 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:
+ � MSS_UART_OVERRUN_ERROR (bit mask = 0x02)
+ � MSS_UART_PARITY_ERROR (bit mask = 0x04)
+ � MSS_UART_FRAMING_ERROR (bit mask = 0x08)
+ � MSS_UART_BREAK_ERROR (bit mask = 0x10)
+ � MSS_UART_FIFO_ERROR (bit mask = 0x80)
+ When the return value is compared to the following bit mask, a non-zero
+ result indicates that no error occurred:
+ � MSS_UART_NO_ERROR (bit mask = 0x00)
+ Upon unsuccessful execution, this function returns:
+ � MSS_UART_INVALID_PARAM (bit mask = 0xFF)
+
+ Example:
+ @code
+ uint8_t rx_data[MAX_RX_DATA_SIZE];
+ uint8_t err_status;
+ err_status = MSS_UART_get_rx_status(&g_mss_uart0);
+
+ if(MSS_UART_NO_ERROR == err_status)
+ {
+ rx_size = MSS_UART_get_rx(&g_mss_uart0, rx_data, MAX_RX_DATA_SIZE);
+ }
+ @endcode
+ */
+uint8_t
+MSS_UART_get_rx_status
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_get_modem_status() function returns the modem status of the
+ MSS UART instance. It reads the modem status register (MSR) and returns
+ the 8 bit value. The bit encoding of the returned value is exactly the
+ same as the definition of the bits in the MSR.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function returns current state of the UART's MSR as an 8 bit
+ unsigned integer. The driver provides the following set of bit mask
+ constants that should be compared with and/or used to mask the
+ returned value to determine the modem status:
+ � MSS_UART_DCTS (bit mask = 0x01)
+ � MSS_UART_DDSR (bit mask = 0x02)
+ � MSS_UART_TERI (bit mask = 0x04)
+ � MSS_UART_DDCD (bit mask = 0x08)
+ � MSS_UART_CTS (bit mask = 0x10)
+ � MSS_UART_DSR (bit mask = 0x20)
+ � MSS_UART_RI (bit mask = 0x40)
+ � MSS_UART_DCD (bit mask = 0x80)
+
+ Example:
+ @code
+ void uart_modem_status_isr(mss_uart_instance_t * this_uart)
+ {
+ uint8_t status;
+ status = MSS_UART_get_modem_status(this_uart);
+ if( status & MSS_UART_DCTS )
+ {
+ uart_dcts_handler();
+ }
+ if( status & MSS_UART_CTS )
+ {
+ uart_cts_handler();
+ }
+ }
+ @endcode
+ */
+uint8_t
+MSS_UART_get_modem_status
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_get_tx_status() function returns the transmitter status of the
+ MSS UART instance. It reads both the UART�s line status register (LSR) and
+ returns the status of the transmit holding register empty (THRE) and
+ transmitter empty (TEMT) bits.*
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function returns the UART�s transmitter status as an 8-bit unsigned
+ integer. The returned value is 0 if the transmitter status bits are not
+ set or the function execution failed. The driver provides a set of bit
+ mask constants that should be compared with and/or used to mask the
+ returned value to determine the transmitter status.
+ When the return value is compared to the following bit mask, a non-zero
+ result indicates that the corresponding transmitter status bit is set:
+ � MSS_UART_THRE (bit mask = 0x20)
+ � MSS_UART_TEMT (bit mask = 0x40)
+ When the return value is compared to the following bit mask, a non-zero
+ result indicates that the transmitter is busy or the function execution
+ failed.
+ � MSS_UART_TX_BUSY (bit mask = 0x00)
+
+ Example:
+ @code
+ uint8_t tx_buff[10] = "abcdefghi";
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_polled_tx(&g_mss_uart0, tx_buff, sizeof(tx_buff));
+
+ while(!(MSS_UART_TEMT & MSS_UART_get_tx_status(&g_mss_uart0)))
+ {
+ ;
+ }
+ @endcode
+ */
+uint8_t
+MSS_UART_get_tx_status
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_break() function is used to send the break
+ (9 zeros after stop bit) signal on the TX line. This function can be used
+ only when the MSS UART is initialized in LIN mode by using MSS_UART_lin_init().
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_break(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_set_break
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_clear_break() function is used to remove the break signal on the
+ TX line. This function can be used only when the MSS UART is initialized in
+ LIN mode by using MSS_UART_lin_init().
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_clear_break(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_clear_break
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_half_duplex() function is used to enable the half-duplex
+ (single wire) mode for the MSS UART. Though it finds application in Smartcard
+ mode, half-duplex mode can be used in other modes as well.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_enable_half_duplex(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_enable_half_duplex
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_half_duplex() function is used to disable the half-duplex
+ (single wire) mode for the MSS UART. Though it finds application in Smartcard
+ mode, half-duplex mode can be used in other modes as well.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_disable_half_duplex(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_disable_half_duplex
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_rx_endian() function is used to configure the LSB first or
+ MSB first setting for MSS UART receiver
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param endian
+ The endian parameter tells the LSB first or MSB first configuration.
+ This parameter is of type mss_uart_endian_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_rx_endian(&g_mss_uart0, MSS_UART_LITTLEEND);
+ @endcode
+ */
+void
+MSS_UART_set_rx_endian
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_endian_t endian
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_tx_endian() function is used to configure the LSB first or
+ MSB first setting for MSS UART transmitter.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param endian
+ The endian parameter tells the LSB first or MSB first configuration.
+ This parameter is of type mss_uart_endian_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_tx_endian(&g_mss_uart0, MSS_UART_LITTLEEND);
+ @endcode
+ */
+void
+MSS_UART_set_tx_endian
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_endian_t endian
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_filter_length () function is used to configure the glitch
+ filter length of the MSS UART. This should be configured in accordance with
+ the chosen baud rate.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param length
+ The length parameter is of mss_uart_filter_length_t type that determines
+ the length of the glitch filter.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_filter_length(&g_mss_uart0, MSS_UART_LEN2);
+ @endcode
+ */
+void
+MSS_UART_set_filter_length
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_filter_length_t length
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_afm() function is used to enable address flag detection
+ mode of the MSS UART
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_enable_afm(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_enable_afm
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_afm() function is used to disable address flag detection
+ mode of the MSS UART.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_disable_afm(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_disable_afm
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_afclear () function is used to enable address flag clear
+ of the MSS UART. This should be used in conjunction with address flag
+ detection mode (AFM).
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_enable_afclear(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_enable_afclear
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_afclear () function is used to disable address flag
+ clear of the MSS UART. This should be used in conjunction with address flag
+ detection mode (AFM).
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_disable_afclear(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_disable_afclear
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_rx_timeout() function is used to enable and configure
+ the receiver timeout functionality of MSS UART. This function accepts the
+ timeout parameter and applies the timeout based up on the baud rate as per
+ the formula 4 x timeout x bit time.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param timeout
+ The timeout parameter specifies the receiver timeout multiple.
+ It should be configured according to the baud rate in use.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_enable_rx_timeout(&g_mss_uart0 , 24);
+ @endcode
+ */
+void
+MSS_UART_enable_rx_timeout
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t timeout
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_rx_timeout() function is used to disable the receiver
+ timeout functionality of MSS UART.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_disable_rx_timeout(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_disable_rx_timeout
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_enable_tx_time_guard() function is used to enable and configure
+ the transmitter time guard functionality of MSS UART. This function accepts
+ the timeguard parameter and applies the timeguard based up on the baud rate
+ as per the formula timeguard x bit time.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_enable_tx_time_guard(&g_mss_uart0 , 24);
+ @endcode
+ */
+void
+MSS_UART_enable_tx_time_guard
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t timeguard
+);
+
+/***************************************************************************//**
+ The MSS_UART_disable_tx_time_guard() function is used to disable the
+ transmitter time guard functionality of MSS UART.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_disable_tx_time_guard(&g_mss_uart0);
+ @endcode
+ */
+void
+MSS_UART_disable_tx_time_guard
+(
+ mss_uart_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_address() function is used to set the 8-bit address for
+ the MSS UART referenced by this_uart parameter.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param address
+ The address parameter is the 8-bit address which is to be configured
+ to the MSS UART referenced by this_uart parameter.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_address(&g_mss_uart0, 0xAA);
+ @endcode
+ */
+void
+MSS_UART_set_address
+(
+ mss_uart_instance_t * this_uart,
+ uint8_t address
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_ready_mode() function is used to configure the MODE0 or MODE1
+ to the TXRDY and RXRDY signals of the MSS UART referenced by this_uart
+ parameter. The mode parameter is used to provide the mode to be configured.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param mode
+ The mode parameter is the mss_uart_ready_mode_t type which is used to
+ configure the TXRDY and RXRDY signal modes.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_ready_mode(&g_mss_uart0, MSS_UART_READY_MODE0);
+ @endcode
+ */
+void
+MSS_UART_set_ready_mode
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_ready_mode_t mode
+);
+
+/***************************************************************************//**
+ The MSS_UART_set_usart_mode() function is used to configure the MSS UART
+ referenced by the parameter this_uart in USART mode. Various USART modes
+ are supported which can be configured by the parameter mode of type
+ mss_uart_usart_mode_t.
+
+ @param this_uart
+ The this_uart parameter is a pointer to an mss_uart_instance_t
+ structure identifying the MSS UART hardware block that will perform
+ the requested function. There are two such data structures,
+ g_mss_uart0 and g_mss_uart1, associated with MSS UART0 and MSS UART1.
+ This parameter must point to either the g_mss_uart0 or g_mss_uart1
+ global data structure defined within the UART driver.
+
+ @param mode
+ The mode parameter is the USART mode to be configured.
+ This parameter is of type mss_uart_usart_mode_t.
+
+ @return
+ This function does not return a value.
+
+ Example:
+ @code
+ MSS_UART_init(&g_mss_uart0,
+ MSS_UART_57600_BAUD,
+ MSS_UART_DATA_8_BITS | MSS_UART_NO_PARITY | MSS_UART_ONE_STOP_BIT);
+
+ MSS_UART_set_usart_mode(&g_mss_uart0, MSS_UART_SYNC_MASTER_POS_EDGE_CLK);
+ @endcode
+ */
+void
+MSS_UART_set_usart_mode
+(
+ mss_uart_instance_t * this_uart,
+ mss_uart_usart_mode_t mode
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MSS_UART_H_ */
diff --git a/bsp/smartfusion2/libraries/mss_uart/mss_uart_regs.h b/bsp/smartfusion2/libraries/mss_uart/mss_uart_regs.h
new file mode 100644
index 0000000000..3079ad4ba3
--- /dev/null
+++ b/bsp/smartfusion2/libraries/mss_uart/mss_uart_regs.h
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * (c) Copyright 2011-2013 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Register bit offsets and masks defintions for SmartFusion2 MSS MMUART.
+ *
+ * SVN $Revision: 5610 $
+ * SVN $Date: 2013-04-05 18:49:30 +0530 (Fri, 05 Apr 2013) $
+ */
+#ifndef MSS_UART_REGS_H_
+#define MSS_UART_REGS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ Register Bit definitions
+ */
+
+/* Line Control register bit definitions */
+#define SB 6u /* Set break */
+#define DLAB 7u /* Divisor latch access bit */
+
+/* FIFO Control register bit definitions */
+#define RXRDY_TXRDYN_EN 0u /* Enable TXRDY and RXRDY signals */
+#define CLEAR_RX_FIFO 1u /* Clear receiver FIFO */
+#define CLEAR_TX_FIFO 2u /* Clear transimtter FIFO */
+#define RDYMODE 3u /* Mode 0 or Mode 1 for TXRDY and RXRDY */
+
+/* Modem Control register bit definitions */
+#define LOOP 4u /* Local loopback */
+#define RLOOP 5u /* Remote loopback */
+#define ECHO 6u /* Automatic echo */
+#define RLOOP_MASK 0x6u /* Remote loopback & Automatic echo*/
+
+/* Line Status register bit definitions */
+#define DR 0u /* Data ready */
+#define THRE 5u /* Transmitter holding register empty */
+#define TEMT 6u /* Transitter empty */
+
+/* Interrupt Enable register bit definitions */
+#define ERBFI 0u /* Enable receiver buffer full interrupt */
+#define ETBEI 1u /* Enable transmitter buffer empty interrupt */
+#define ELSI 2u /* Enable line status interrupt */
+#define EDSSI 3u /* Enable modem status interrupt */
+
+/* Multimode register 0 bit definitions */
+#define ELIN 3u /* Enable LIN header detection */
+#define ETTG 5u /* Enable transmitter time guard */
+#define ERTO 6u /* Enable receiver time-out */
+#define EFBR 7u /* Enable fractional baud rate mode */
+
+/* Multimode register 1 bit definitions */
+#define E_MSB_RX 0u /* MSB / LSB first for receiver */
+#define E_MSB_TX 1u /* MSB / LSB first for transmitter */
+#define EIRD 2u /* Enable IrDA modem */
+#define EIRX 3u /* Input polarity for IrDA modem */
+#define EITX 4u /* Output polarity for IrDA modem */
+#define EITP 5u /* Output pulse width for IrDA modem */
+
+/* Multimode register 2 bit definitions */
+#define EERR 0u /* Enable ERR / NACK during stop time */
+#define EAFM 1u /* Enable 9-bit address flag mode */
+#define EAFC 2u /* Enable address flag clear */
+#define ESWM 3u /* Enable single wire half-duplex mode */
+
+/* Multimode Interrupt Enable register and
+ Multimode Interrupt Identification register definitions */
+#define ERTOI 0u /* Enable receiver timeout interrupt */
+#define ENACKI 1u /* Enable NACK / ERR interrupt */
+#define EPID_PEI 2u /* Enable PID parity error interrupt */
+#define ELINBI 3u /* Enable LIN break interrupt */
+#define ELINSI 4u /* Enable LIN sync detection interrupt */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MSS_UART_REGS_H_ */
+
+
+
diff --git a/bsp/smartfusion2/libraries/sys_config/sys_config.c b/bsp/smartfusion2/libraries/sys_config/sys_config.c
new file mode 100644
index 0000000000..b7d72fe08f
--- /dev/null
+++ b/bsp/smartfusion2/libraries/sys_config/sys_config.c
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * (c) Copyright 2012 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Smartfusion2 system configuration. This file is automatically generated
+ * by the Libero tools. It contains the Smartfusion2 system configuration that
+ * was selected during the hardware configuration flow.
+ *
+ */
+
+#include "../../CMSIS/m2sxxx.h"
+#include "../../CMSIS/sys_init_cfg_types.h"
+#include "sys_config.h"
+
+/*==============================================================================
+ * !!! WARNING !!!
+ *==============================================================================
+ * The project including this file must be linked so that the content of this
+ * file is located in internal eNVM at run time. The content of this file is
+ * used to configure the system prior to RAM content initialization. This means
+ * that the content of the data structures below will be used before the copy
+ * from LMA to VMA takes place. The LMA and VMA locations of the content of this
+ * file must be identical for the system to be seamlessly configured as part of
+ * the CMSIS boot process.
+ */
+
+/*==============================================================================
+ * Clock configuration
+ */
+/* No configuration data structure required. */
+
+/*==============================================================================
+ * Memory remapping configuration
+ */
+/* TBD. */
+
+/*==============================================================================
+ * MDDR configuration
+ */
+#if MSS_SYS_MDDR_CONFIG_BY_CORTEX
+
+#include "sys_config_mddr_define.h"
+
+MDDR_TypeDef * const g_m2s_mddr_addr = (MDDR_TypeDef *)0x40020800;
+
+const ddr_subsys_cfg_t g_m2s_mddr_subsys_config =
+{
+ /*---------------------------------------------------------------------
+ * DDR Controller registers.
+ * All registers are 16-bit wide unless mentioned beside the definition.
+ */
+ {
+ MDDR_DDRC_DYN_SOFT_RESET_CR,
+ MDDR_DDRC_RESERVED0,
+ MDDR_DDRC_DYN_REFRESH_1_CR,
+ MDDR_DDRC_DYN_REFRESH_2_CR,
+ MDDR_DDRC_DYN_POWERDOWN_CR,
+ MDDR_DDRC_DYN_DEBUG_CR,
+ MDDR_DDRC_MODE_CR,
+ MDDR_DDRC_ADDR_MAP_BANK_CR,
+ MDDR_DDRC_ECC_DATA_MASK_CR,
+ MDDR_DDRC_ADDR_MAP_COL_1_CR,
+ MDDR_DDRC_ADDR_MAP_COL_2_CR,
+ MDDR_DDRC_ADDR_MAP_ROW_1_CR,
+ MDDR_DDRC_ADDR_MAP_ROW_2_CR,
+ MDDR_DDRC_INIT_1_CR,
+ MDDR_DDRC_CKE_RSTN_CYCLES_1_CR,
+ MDDR_DDRC_CKE_RSTN_CYCLES_2_CR,
+ MDDR_DDRC_INIT_MR_CR,
+ MDDR_DDRC_INIT_EMR_CR,
+ MDDR_DDRC_INIT_EMR2_CR,
+ MDDR_DDRC_INIT_EMR3_CR,
+ MDDR_DDRC_DRAM_BANK_TIMING_PARAM_CR,
+ MDDR_DDRC_DRAM_RD_WR_LATENCY_CR,
+ MDDR_DDRC_DRAM_RD_WR_PRE_CR,
+ MDDR_DDRC_DRAM_MR_TIMING_PARAM_CR,
+ MDDR_DDRC_DRAM_RAS_TIMING_CR,
+ MDDR_DDRC_DRAM_RD_WR_TRNARND_TIME_CR,
+ MDDR_DDRC_DRAM_T_PD_CR,
+ MDDR_DDRC_DRAM_BANK_ACT_TIMING_CR,
+ MDDR_DDRC_ODT_PARAM_1_CR,
+ MDDR_DDRC_ODT_PARAM_2_CR,
+ MDDR_DDRC_ADDR_MAP_COL_3_CR,
+ MDDR_DDRC_MODE_REG_RD_WR_CR,
+ MDDR_DDRC_MODE_REG_DATA_CR,
+ MDDR_DDRC_PWR_SAVE_1_CR,
+ MDDR_DDRC_PWR_SAVE_2_CR,
+ MDDR_DDRC_ZQ_LONG_TIME_CR,
+ MDDR_DDRC_ZQ_SHORT_TIME_CR,
+ MDDR_DDRC_ZQ_SHORT_INT_REFRESH_MARGIN_1_CR,
+ MDDR_DDRC_ZQ_SHORT_INT_REFRESH_MARGIN_2_CR,
+ MDDR_DDRC_PERF_PARAM_1_CR,
+ MDDR_DDRC_HPR_QUEUE_PARAM_1_CR,
+ MDDR_DDRC_HPR_QUEUE_PARAM_2_CR,
+ MDDR_DDRC_LPR_QUEUE_PARAM_1_CR,
+ MDDR_DDRC_LPR_QUEUE_PARAM_2_CR,
+ MDDR_DDRC_WR_QUEUE_PARAM_CR,
+ MDDR_DDRC_PERF_PARAM_2_CR,
+ MDDR_DDRC_PERF_PARAM_3_CR,
+ MDDR_DDRC_DFI_RDDATA_EN_CR,
+ MDDR_DDRC_DFI_MIN_CTRLUPD_TIMING_CR,
+ MDDR_DDRC_DFI_MAX_CTRLUPD_TIMING_CR,
+ MDDR_DDRC_DFI_WR_LVL_CONTROL_1_CR,
+ MDDR_DDRC_DFI_WR_LVL_CONTROL_2_CR,
+ MDDR_DDRC_DFI_RD_LVL_CONTROL_1_CR,
+ MDDR_DDRC_DFI_RD_LVL_CONTROL_2_CR,
+ MDDR_DDRC_DFI_CTRLUPD_TIME_INTERVAL_CR,
+ MDDR_DDRC_DYN_SOFT_RESET_ALIAS_CR,
+ MDDR_DDRC_AXI_FABRIC_PRI_ID_CR,
+ },
+
+ /*---------------------------------------------------------------------
+ * DDR PHY configuration registers
+ */
+ {
+ MDDR_PHY_LOOPBACK_TEST_CR,
+ MDDR_PHY_BOARD_LOOPBACK_CR,
+ MDDR_PHY_CTRL_SLAVE_RATIO_CR,
+ MDDR_PHY_CTRL_SLAVE_FORCE_CR,
+ MDDR_PHY_CTRL_SLAVE_DELAY_CR,
+ MDDR_PHY_DATA_SLICE_IN_USE_CR,
+ MDDR_PHY_LVL_NUM_OF_DQ0_CR,
+ MDDR_PHY_DQ_OFFSET_1_CR,
+ MDDR_PHY_DQ_OFFSET_2_CR,
+ MDDR_PHY_DQ_OFFSET_3_CR,
+ MDDR_PHY_DIS_CALIB_RST_CR,
+ MDDR_PHY_DLL_LOCK_DIFF_CR,
+ MDDR_PHY_FIFO_WE_IN_DELAY_1_CR,
+ MDDR_PHY_FIFO_WE_IN_DELAY_2_CR,
+ MDDR_PHY_FIFO_WE_IN_DELAY_3_CR,
+ MDDR_PHY_FIFO_WE_IN_FORCE_CR,
+ MDDR_PHY_FIFO_WE_SLAVE_RATIO_1_CR,
+ MDDR_PHY_FIFO_WE_SLAVE_RATIO_2_CR,
+ MDDR_PHY_FIFO_WE_SLAVE_RATIO_3_CR,
+ MDDR_PHY_FIFO_WE_SLAVE_RATIO_4_CR,
+ MDDR_PHY_GATELVL_INIT_MODE_CR,
+ MDDR_PHY_GATELVL_INIT_RATIO_1_CR,
+ MDDR_PHY_GATELVL_INIT_RATIO_2_CR,
+ MDDR_PHY_GATELVL_INIT_RATIO_3_CR,
+ MDDR_PHY_GATELVL_INIT_RATIO_4_CR,
+ MDDR_PHY_LOCAL_ODT_CR,
+ MDDR_PHY_INVERT_CLKOUT_CR,
+ MDDR_PHY_RD_DQS_SLAVE_DELAY_1_CR,
+ MDDR_PHY_RD_DQS_SLAVE_DELAY_2_CR,
+ MDDR_PHY_RD_DQS_SLAVE_DELAY_3_CR,
+ MDDR_PHY_RD_DQS_SLAVE_FORCE_CR,
+ MDDR_PHY_RD_DQS_SLAVE_RATIO_1_CR,
+ MDDR_PHY_RD_DQS_SLAVE_RATIO_2_CR,
+ MDDR_PHY_RD_DQS_SLAVE_RATIO_3_CR,
+ MDDR_PHY_RD_DQS_SLAVE_RATIO_4_CR,
+ MDDR_PHY_WR_DQS_SLAVE_DELAY_1_CR,
+ MDDR_PHY_WR_DQS_SLAVE_DELAY_2_CR,
+ MDDR_PHY_WR_DQS_SLAVE_DELAY_3_CR,
+ MDDR_PHY_WR_DQS_SLAVE_FORCE_CR,
+ MDDR_PHY_WR_DQS_SLAVE_RATIO_1_CR,
+ MDDR_PHY_WR_DQS_SLAVE_RATIO_2_CR,
+ MDDR_PHY_WR_DQS_SLAVE_RATIO_3_CR,
+ MDDR_PHY_WR_DQS_SLAVE_RATIO_4_CR,
+ MDDR_PHY_WR_DATA_SLAVE_DELAY_1_CR,
+ MDDR_PHY_WR_DATA_SLAVE_DELAY_2_CR,
+ MDDR_PHY_WR_DATA_SLAVE_DELAY_3_CR,
+ MDDR_PHY_WR_DATA_SLAVE_FORCE_CR,
+ MDDR_PHY_WR_DATA_SLAVE_RATIO_1_CR,
+ MDDR_PHY_WR_DATA_SLAVE_RATIO_2_CR,
+ MDDR_PHY_WR_DATA_SLAVE_RATIO_3_CR,
+ MDDR_PHY_WR_DATA_SLAVE_RATIO_4_CR,
+ MDDR_PHY_WRLVL_INIT_MODE_CR,
+ MDDR_PHY_WRLVL_INIT_RATIO_1_CR,
+ MDDR_PHY_WRLVL_INIT_RATIO_2_CR,
+ MDDR_PHY_WRLVL_INIT_RATIO_3_CR,
+ MDDR_PHY_WRLVL_INIT_RATIO_4_CR,
+ MDDR_PHY_WR_RD_RL_CR,
+ MDDR_PHY_RDC_FIFO_RST_ERR_CNT_CLR_CR,
+ MDDR_PHY_RDC_WE_TO_RE_DELAY_CR,
+ MDDR_PHY_USE_FIXED_RE_CR,
+ MDDR_PHY_USE_RANK0_DELAYS_CR,
+ MDDR_PHY_USE_LVL_TRNG_LEVEL_CR,
+ MDDR_PHY_DYN_CONFIG_CR,
+ MDDR_PHY_RD_WR_GATE_LVL_CR,
+ MDDR_PHY_DYN_RESET_CR
+ },
+
+ /*---------------------------------------------------------------------
+ * FIC-64 registers
+ * These registers are 16-bit wide and 32-bit aligned.
+ */
+ {
+ MDDR_DDR_FIC_NB_ADDR_CR,
+ MDDR_DDR_FIC_NBRWB_SIZE_CR,
+ MDDR_DDR_FIC_WB_TIMEOUT_CR,
+ MDDR_DDR_FIC_HPD_SW_RW_EN_CR,
+ MDDR_DDR_FIC_HPD_SW_RW_INVAL_CR,
+ MDDR_DDR_FIC_SW_WR_ERCLR_CR,
+ MDDR_DDR_FIC_ERR_INT_ENABLE_CR,
+ MDDR_DDR_FIC_NUM_AHB_MASTERS_CR,
+ MDDR_DDR_FIC_LOCK_TIMEOUTVAL_1_CR,
+ MDDR_DDR_FIC_LOCK_TIMEOUTVAL_2_CR,
+ MDDR_DDR_FIC_LOCK_TIMEOUT_EN_CR
+ }
+};
+
+#endif
+
+/*==============================================================================
+ * FDDR configuration
+ */
+#if MSS_SYS_FDDR_CONFIG_BY_CORTEX
+
+#include "sys_config_fddr_define.h"
+
+FDDR_TypeDef * const g_m2s_fddr_addr = (FDDR_TypeDef *)0x40021000;
+
+const fddr_sysreg_t g_m2s_fddr_sysreg_subsys_config =
+{
+ 0x0001u, /* PLL_CONFIG_LOW_1 */
+ 0x0002u, /* PLL_CONFIG_LOW_2 */
+ 0x0003u, /* PLL_CONFIG_HIGH */
+ 0x0004u, /* FACC_CLK_EN */
+ 0x0005u, /* FACC_MUX_CONFIG */
+ 0x0006u, /* FACC_DIVISOR_RATIO */
+ 0x0007u, /* PLL_DELAY_LINE_SEL */
+ 0x0008u, /* SOFT_RESET */
+ 0x0009u, /* IO_CALIB */
+ 0x000Au, /* INTERRUPT_ENABLE */
+ 0x000Bu, /* AXI_AHB_MODE_SEL */
+ 0x000Cu /* PHY_SELF_REF_EN */
+};
+
+const ddr_subsys_cfg_t g_m2s_fddr_subsys_config =
+{
+ /*---------------------------------------------------------------------
+ * DDR Controller registers.
+ * All registers are 16-bit wide unless mentioned beside the definition.
+ */
+ {
+ FDDR_DDRC_DYN_SOFT_RESET_CR,
+ FDDR_DDRC_RESERVED0,
+ FDDR_DDRC_DYN_REFRESH_1_CR,
+ FDDR_DDRC_DYN_REFRESH_2_CR,
+ FDDR_DDRC_DYN_POWERDOWN_CR,
+ FDDR_DDRC_DYN_DEBUG_CR,
+ FDDR_DDRC_MODE_CR,
+ FDDR_DDRC_ADDR_MAP_BANK_CR,
+ FDDR_DDRC_ECC_DATA_MASK_CR,
+ FDDR_DDRC_ADDR_MAP_COL_1_CR,
+ FDDR_DDRC_ADDR_MAP_COL_2_CR,
+ FDDR_DDRC_ADDR_MAP_ROW_1_CR,
+ FDDR_DDRC_ADDR_MAP_ROW_2_CR,
+ FDDR_DDRC_INIT_1_CR,
+ FDDR_DDRC_CKE_RSTN_CYCLES_1_CR,
+ FDDR_DDRC_CKE_RSTN_CYCLES_2_CR,
+ FDDR_DDRC_INIT_MR_CR,
+ FDDR_DDRC_INIT_EMR_CR,
+ FDDR_DDRC_INIT_EMR2_CR,
+ FDDR_DDRC_INIT_EMR3_CR,
+ FDDR_DDRC_DRAM_BANK_TIMING_PARAM_CR,
+ FDDR_DDRC_DRAM_RD_WR_LATENCY_CR,
+ FDDR_DDRC_DRAM_RD_WR_PRE_CR,
+ FDDR_DDRC_DRAM_MR_TIMING_PARAM_CR,
+ FDDR_DDRC_DRAM_RAS_TIMING_CR,
+ FDDR_DDRC_DRAM_RD_WR_TRNARND_TIME_CR,
+ FDDR_DDRC_DRAM_T_PD_CR,
+ FDDR_DDRC_DRAM_BANK_ACT_TIMING_CR,
+ FDDR_DDRC_ODT_PARAM_1_CR,
+ FDDR_DDRC_ODT_PARAM_2_CR,
+ FDDR_DDRC_ADDR_MAP_COL_3_CR,
+ FDDR_DDRC_MODE_REG_RD_WR_CR,
+ FDDR_DDRC_MODE_REG_DATA_CR,
+ FDDR_DDRC_PWR_SAVE_1_CR,
+ FDDR_DDRC_PWR_SAVE_2_CR,
+ FDDR_DDRC_ZQ_LONG_TIME_CR,
+ FDDR_DDRC_ZQ_SHORT_TIME_CR,
+ FDDR_DDRC_ZQ_SHORT_INT_REFRESH_MARGIN_1_CR,
+ FDDR_DDRC_ZQ_SHORT_INT_REFRESH_MARGIN_2_CR,
+ FDDR_DDRC_PERF_PARAM_1_CR,
+ FDDR_DDRC_HPR_QUEUE_PARAM_1_CR,
+ FDDR_DDRC_HPR_QUEUE_PARAM_2_CR,
+ FDDR_DDRC_LPR_QUEUE_PARAM_1_CR,
+ FDDR_DDRC_LPR_QUEUE_PARAM_2_CR,
+ FDDR_DDRC_WR_QUEUE_PARAM_CR,
+ FDDR_DDRC_PERF_PARAM_2_CR,
+ FDDR_DDRC_PERF_PARAM_3_CR,
+ FDDR_DDRC_DFI_RDDATA_EN_CR,
+ FDDR_DDRC_DFI_MIN_CTRLUPD_TIMING_CR,
+ FDDR_DDRC_DFI_MAX_CTRLUPD_TIMING_CR,
+ FDDR_DDRC_DFI_WR_LVL_CONTROL_1_CR,
+ FDDR_DDRC_DFI_WR_LVL_CONTROL_2_CR,
+ FDDR_DDRC_DFI_RD_LVL_CONTROL_1_CR,
+ FDDR_DDRC_DFI_RD_LVL_CONTROL_2_CR,
+ FDDR_DDRC_DFI_CTRLUPD_TIME_INTERVAL_CR,
+ FDDR_DDRC_DYN_SOFT_RESET_ALIAS_CR,
+ FDDR_DDRC_AXI_FABRIC_PRI_ID_CR
+ },
+
+ /*---------------------------------------------------------------------
+ * DDR PHY configuration registers
+ */
+ {
+ FDDR_PHY_LOOPBACK_TEST_CR,
+ FDDR_PHY_BOARD_LOOPBACK_CR,
+ FDDR_PHY_CTRL_SLAVE_RATIO_CR,
+ FDDR_PHY_CTRL_SLAVE_FORCE_CR,
+ FDDR_PHY_CTRL_SLAVE_DELAY_CR,
+ FDDR_PHY_DATA_SLICE_IN_USE_CR,
+ FDDR_PHY_LVL_NUM_OF_DQ0_CR,
+ FDDR_PHY_DQ_OFFSET_1_CR,
+ FDDR_PHY_DQ_OFFSET_2_CR,
+ FDDR_PHY_DQ_OFFSET_3_CR,
+ FDDR_PHY_DIS_CALIB_RST_CR,
+ FDDR_PHY_DLL_LOCK_DIFF_CR,
+ FDDR_PHY_FIFO_WE_IN_DELAY_1_CR,
+ FDDR_PHY_FIFO_WE_IN_DELAY_2_CR,
+ FDDR_PHY_FIFO_WE_IN_DELAY_3_CR,
+ FDDR_PHY_FIFO_WE_IN_FORCE_CR,
+ FDDR_PHY_FIFO_WE_SLAVE_RATIO_1_CR,
+ FDDR_PHY_FIFO_WE_SLAVE_RATIO_2_CR,
+ FDDR_PHY_FIFO_WE_SLAVE_RATIO_3_CR,
+ FDDR_PHY_FIFO_WE_SLAVE_RATIO_4_CR,
+ FDDR_PHY_GATELVL_INIT_MODE_CR,
+ FDDR_PHY_GATELVL_INIT_RATIO_1_CR,
+ FDDR_PHY_GATELVL_INIT_RATIO_2_CR,
+ FDDR_PHY_GATELVL_INIT_RATIO_3_CR,
+ FDDR_PHY_GATELVL_INIT_RATIO_4_CR,
+ FDDR_PHY_LOCAL_ODT_CR,
+ FDDR_PHY_INVERT_CLKOUT_CR,
+ FDDR_PHY_RD_DQS_SLAVE_DELAY_1_CR,
+ FDDR_PHY_RD_DQS_SLAVE_DELAY_2_CR,
+ FDDR_PHY_RD_DQS_SLAVE_DELAY_3_CR,
+ FDDR_PHY_RD_DQS_SLAVE_FORCE_CR,
+ FDDR_PHY_RD_DQS_SLAVE_RATIO_1_CR,
+ FDDR_PHY_RD_DQS_SLAVE_RATIO_2_CR,
+ FDDR_PHY_RD_DQS_SLAVE_RATIO_3_CR,
+ FDDR_PHY_RD_DQS_SLAVE_RATIO_4_CR,
+ FDDR_PHY_WR_DQS_SLAVE_DELAY_1_CR,
+ FDDR_PHY_WR_DQS_SLAVE_DELAY_2_CR,
+ FDDR_PHY_WR_DQS_SLAVE_DELAY_3_CR,
+ FDDR_PHY_WR_DQS_SLAVE_FORCE_CR,
+ FDDR_PHY_WR_DQS_SLAVE_RATIO_1_CR,
+ FDDR_PHY_WR_DQS_SLAVE_RATIO_2_CR,
+ FDDR_PHY_WR_DQS_SLAVE_RATIO_3_CR,
+ FDDR_PHY_WR_DQS_SLAVE_RATIO_4_CR,
+ FDDR_PHY_WR_DATA_SLAVE_DELAY_1_CR,
+ FDDR_PHY_WR_DATA_SLAVE_DELAY_2_CR,
+ FDDR_PHY_WR_DATA_SLAVE_DELAY_3_CR,
+ FDDR_PHY_WR_DATA_SLAVE_FORCE_CR,
+ FDDR_PHY_WR_DATA_SLAVE_RATIO_1_CR,
+ FDDR_PHY_WR_DATA_SLAVE_RATIO_2_CR,
+ FDDR_PHY_WR_DATA_SLAVE_RATIO_3_CR,
+ FDDR_PHY_WR_DATA_SLAVE_RATIO_4_CR,
+ FDDR_PHY_WRLVL_INIT_MODE_CR,
+ FDDR_PHY_WRLVL_INIT_RATIO_1_CR,
+ FDDR_PHY_WRLVL_INIT_RATIO_2_CR,
+ FDDR_PHY_WRLVL_INIT_RATIO_3_CR,
+ FDDR_PHY_WRLVL_INIT_RATIO_4_CR,
+ FDDR_PHY_WR_RD_RL_CR,
+ FDDR_PHY_RDC_FIFO_RST_ERR_CNT_CLR_CR,
+ FDDR_PHY_RDC_WE_TO_RE_DELAY_CR,
+ FDDR_PHY_USE_FIXED_RE_CR,
+ FDDR_PHY_USE_RANK0_DELAYS_CR,
+ FDDR_PHY_USE_LVL_TRNG_LEVEL_CR,
+ FDDR_PHY_DYN_CONFIG_CR,
+ FDDR_PHY_RD_WR_GATE_LVL_CR,
+ FDDR_PHY_DYN_RESET_CR,
+ },
+
+ /*---------------------------------------------------------------------
+ * FIC-64 registers
+ * These registers are 16-bit wide and 32-bit aligned.
+ */
+ {
+ FDDR_DDR_FIC_NB_ADDR_CR,
+ FDDR_DDR_FIC_NBRWB_SIZE_CR,
+ FDDR_DDR_FIC_WB_TIMEOUT_CR,
+ FDDR_DDR_FIC_HPD_SW_RW_EN_CR,
+ FDDR_DDR_FIC_HPD_SW_RW_INVAL_CR,
+ FDDR_DDR_FIC_SW_WR_ERCLR_CR,
+ FDDR_DDR_FIC_ERR_INT_ENABLE_CR,
+ FDDR_DDR_FIC_NUM_AHB_MASTERS_CR,
+ FDDR_DDR_FIC_LOCK_TIMEOUTVAL_1_CR,
+ FDDR_DDR_FIC_LOCK_TIMEOUTVAL_2_CR,
+ FDDR_DDR_FIC_LOCK_TIMEOUT_EN_CR
+ }
+};
+
+#endif
+
diff --git a/bsp/smartfusion2/libraries/sys_config/sys_config.h b/bsp/smartfusion2/libraries/sys_config/sys_config.h
new file mode 100644
index 0000000000..65c49b1d7d
--- /dev/null
+++ b/bsp/smartfusion2/libraries/sys_config/sys_config.h
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * (c) Copyright 2012 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Smartfusion2 system configuration. This file is automatically generated
+ * by the Libero tools.
+ *
+ */
+#ifndef MSS_SYSTEM_CONFIGURATION
+#define MSS_SYSTEM_CONFIGURATION
+
+/*==============================================================================
+ * Clock configuration
+ */
+#include "sys_config_mss_clocks.h"
+
+/*==============================================================================
+ * Memory remapping configuration
+ */
+/* TBD */
+
+/*==============================================================================
+ * FACC_INIT (Cortex-M3 runs the FACC INIT procedure)
+ * Only set to 1 for design targeting the M2S050T_ES device
+ */
+#define MSS_SYS_FACC_INIT_BY_CORTEX 0
+
+/*==============================================================================
+ * MDDR configuration
+ */
+#define MSS_SYS_MDDR_CONFIG_BY_CORTEX 0
+
+/*==============================================================================
+ * FDDR configuration
+ */
+#define MSS_SYS_FDDR_CONFIG_BY_CORTEX 0
+
+/*==============================================================================
+ * SERDES Interface configuration
+ */
+#define MSS_SYS_SERDES_0_CONFIG_BY_CORTEX 0
+#if MSS_SYS_SERDES_0_CONFIG_BY_CORTEX
+#include "sys_config_SERDESIF_0.h"
+#endif
+
+#define MSS_SYS_SERDES_1_CONFIG_BY_CORTEX 0
+#if MSS_SYS_SERDES_1_CONFIG_BY_CORTEX
+#include "sys_config_SERDESIF_1.h"
+#endif
+
+#define MSS_SYS_SERDES_2_CONFIG_BY_CORTEX 0
+#if MSS_SYS_SERDES_2_CONFIG_BY_CORTEX
+#include "sys_config_SERDESIF_2.h"
+#endif
+
+#define MSS_SYS_SERDES_3_CONFIG_BY_CORTEX 0
+#if MSS_SYS_SERDES_3_CONFIG_BY_CORTEX
+#include "sys_config_SERDESIF_3.h"
+#endif
+
+/*==============================================================================
+ * Cache configuration
+ */
+#define MSS_SYS_CACHE_CONFIG_BY_CORTEX 0
+
+#endif /* MSS_SYSTEM_CONFIGURATION */
+
diff --git a/bsp/smartfusion2/libraries/sys_config/sys_config_mss_clocks.h b/bsp/smartfusion2/libraries/sys_config/sys_config_mss_clocks.h
new file mode 100644
index 0000000000..1110c97169
--- /dev/null
+++ b/bsp/smartfusion2/libraries/sys_config/sys_config_mss_clocks.h
@@ -0,0 +1,21 @@
+/*=============================================================*/
+/* Created by Microsemi SmartDesign Fri May 22 15:04:18 2020 */
+/* */
+/* Warning: Do not modify this file, it may lead to unexpected */
+/* functional failures in your design. */
+/* */
+/*=============================================================*/
+
+#ifndef SYS_CONFIG_MSS_CLOCKS
+#define SYS_CONFIG_MSS_CLOCKS
+
+#define MSS_SYS_M3_CLK_FREQ 100000000u
+#define MSS_SYS_MDDR_CLK_FREQ 100000000u
+#define MSS_SYS_APB_0_CLK_FREQ 100000000u
+#define MSS_SYS_APB_1_CLK_FREQ 100000000u
+#define MSS_SYS_APB_2_CLK_FREQ 25000000u
+#define MSS_SYS_FIC_0_CLK_FREQ 100000000u
+#define MSS_SYS_FIC_1_CLK_FREQ 100000000u
+#define MSS_SYS_FIC64_CLK_FREQ 100000000u
+
+#endif /* SYS_CONFIG_MSS_CLOCKS */