diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject
new file mode 100644
index 000000000..c1655cff0
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project
new file mode 100644
index 000000000..f7313f56f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project
@@ -0,0 +1,162 @@
+
+
+ RTOSDemo
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
+
+ FreeRTOS_Source
+ 2
+ FREERTOS_ROOT/FreeRTOS/Source
+
+
+
+
+ 1529524430510
+ FreeRTOS_Source
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-include
+
+
+
+ 1529524430514
+ FreeRTOS_Source
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-portable
+
+
+
+ 1529524430518
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-event_groups.c
+
+
+
+ 1529524430521
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-list.c
+
+
+
+ 1529524430525
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-queue.c
+
+
+
+ 1529524430529
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-stream_buffer.c
+
+
+
+ 1529524430533
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-tasks.c
+
+
+
+ 1529524430538
+ FreeRTOS_Source
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-timers.c
+
+
+
+ 1529524475525
+ FreeRTOS_Source/portable
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-ThirdParty
+
+
+
+ 1529524475530
+ FreeRTOS_Source/portable
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-MemMang
+
+
+
+ 1529524494421
+ FreeRTOS_Source/portable/MemMang
+ 5
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-heap_4.c
+
+
+
+ 1529524515837
+ FreeRTOS_Source/portable/ThirdParty
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-GCC
+
+
+
+ 1529524627661
+ FreeRTOS_Source/portable/ThirdParty/GCC
+ 9
+
+ org.eclipse.ui.ide.multiFilter
+ 1.0-name-matches-false-false-RISC-V
+
+
+
+
+
+ FREERTOS_ROOT
+ $%7BPARENT-3-PROJECT_LOC%7D
+
+
+ copy_PARENT
+ $%7BPARENT-4-PROJECT_LOC%7D/FreeRTOS/WorkingCopy/FreeRTOS
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.settings/language.settings.xml b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.settings/language.settings.xml
new file mode 100644
index 000000000..6dc13a6a3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.settings/language.settings.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h
new file mode 100644
index 000000000..0cd797d12
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h
@@ -0,0 +1,151 @@
+/*
+ FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+ All rights reserved
+
+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+ This file is part of the FreeRTOS distribution.
+
+ FreeRTOS is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License (version 2) as published by the
+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+ ***************************************************************************
+ >>! NOTE: The modification to the GPL is included to allow you to !<<
+ >>! distribute a combined work that includes FreeRTOS without being !<<
+ >>! obliged to provide the source code for proprietary components !<<
+ >>! outside of the FreeRTOS kernel. !<<
+ ***************************************************************************
+
+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. Full license text is available on the following
+ link: http://www.freertos.org/a00114.html
+
+ ***************************************************************************
+ * *
+ * FreeRTOS provides completely free yet professionally developed, *
+ * robust, strictly quality controlled, supported, and cross *
+ * platform software that is more than just the market leader, it *
+ * is the industry's de facto standard. *
+ * *
+ * Help yourself get started quickly while simultaneously helping *
+ * to support the FreeRTOS project by purchasing a FreeRTOS *
+ * tutorial book, reference manual, or both: *
+ * http://www.FreeRTOS.org/Documentation *
+ * *
+ ***************************************************************************
+
+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
+ the FAQ page "My application does not run, what could be wrong?". Have you
+ defined configASSERT()?
+
+ http://www.FreeRTOS.org/support - In return for receiving this top quality
+ embedded software for free we request you assist our global community by
+ participating in the support forum.
+
+ http://www.FreeRTOS.org/training - Investing in training allows your team to
+ be as productive as possible as early as possible. Now you can receive
+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ Ltd, and the world's leading authority on the world's leading RTOS.
+
+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
+ licenses offer ticketed support, indemnification and commercial middleware.
+
+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+ engineered and independently SIL3 certified version for use in safety and
+ mission critical applications that require provable dependability.
+
+ 1 tab == 4 spaces!
+*/
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#include
+#include
+#include "riscv_plic.h"
+
+extern uint32_t SystemCoreClock;
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 1
+#define configUSE_TICK_HOOK 0
+#define configCPU_CLOCK_HZ ( ( unsigned long ) 83000000 )
+#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
+#define configMAX_PRIORITIES ( 5 )
+#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 1024 )
+#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 100 * 1024 ) )
+#define configMAX_TASK_NAME_LEN ( 16 )
+#define configUSE_TRACE_FACILITY 1
+#define configUSE_16_BIT_TICKS 0
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configCHECK_FOR_STACK_OVERFLOW 0 //2
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_MALLOC_FAILED_HOOK 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configGENERATE_RUN_TIME_STATS 0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Software timer definitions. */
+#define configUSE_TIMERS 0
+#define configTIMER_TASK_PRIORITY ( 2 )
+#define configTIMER_QUEUE_LENGTH 2
+#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE )
+
+/* Task priorities. Allow these to be overridden. */
+#ifndef uartPRIMARY_PRIORITY
+ #define uartPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 )
+#endif
+
+/* Set the following definitions to 1 to include the API function, or zero
+to exclude the API function. */
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskCleanUpResources 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_eTaskGetState 1
+
+/* Normal assert() semantics without relying on the provision of an assert.h
+header file. */
+#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names - or at least those used in the unmodified vector table. */
+#define vPortSVCHandler SVCall_Handler
+#define xPortPendSVHandler PendSV_Handler
+#define vPortSysTickHandler SysTick_Handler
+
+extern void vApplicationMallocFailedHook();
+#endif /* FREERTOS_CONFIG_H */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/README.md b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/README.md
new file mode 100644
index 000000000..211d2466d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/README.md
@@ -0,0 +1,48 @@
+## FreeRTOS port for Mi-V Soft Processor
+
+### HW Platform and FPGA design:
+This project is tested on following hardware platforms:
+
+RISCV-Creative-Board
+- [RISC-V Creative board Mi-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/RISC-V-Creative-Board/tree/master/Programming_The_Target_Device/PROC_SUBSYSTEM_MIV_RV32IMA_BaseDesign)
+
+PolarFire-Eval-Kit
+- [PolarFire Eval Kit RISC-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/PolarFire-Eval-Kit/tree/master/Programming_The_Target_Device/MIV_RV32IMA_L1_AHB_BaseDesign)
+
+SmartFusion2-Advanced-Dev-Kit
+- [SmartFusion2 Advanced Development Kit RISC-V Sample Design](https://github.com/RISCV-on-Microsemi-FPGA/SmartFusion2-Advanced-Dev-Kit/tree/master/Programming_The_Target_Device/PROC_SUBSYSTEM_BaseDesign)
+
+### How to run the FreeRTOS RISC-V port:
+To know how to use the SoftConsole workspace, please refer the [Readme.md](https://github.com/RISCV-on-Microsemi-FPGA/SoftConsole/blob/master/README.md)
+
+The miv-rv32im-freertos-port-test is a self contained project. This project demonstrates
+the FreeRTOS running with Microsemi RISC-V processor. This project creates two
+tasks and runs them at regular intervals.
+
+This example project requires USB-UART interface to be connected to a host PC.
+The host PC must connect to the serial port using a terminal emulator such as
+TeraTerm or PuTTY configured as follows:
+
+ - 115200 baud
+ - 8 data bits
+ - 1 stop bit
+ - no parity
+ - no flow control
+
+The ./hw_platform.h file contains the design related information that is required
+for this project. If you update the design, the hw_platform.h must be updated
+accordingly.
+
+### FreeRTOS Configurations
+You must configure the FreeRTOS as per your applications need. Please read and modify FreeRTOSConfig.h.
+E.g. You must set configCPU_CLOCK_HZ parameter in FreeRTOSConfig.h according to the hardware platform
+design that you are using.
+
+The RISC-V creative board design uses 66Mhz processor clock. The PolarFire Eval Kit design uses 50Mhz processor clock. The SmartFusion2 Adv. Development kit design uses 83Mhz processor clock.
+
+### Microsemi SoftConsole Toolchain
+To know more please refer: [SoftConsole](https://github.com/RISCV-on-Microsemi-FPGA/SoftConsole)
+
+### Documentation for Microsemi RISC-V processor, SoftConsole toochain, Debug Tools, FPGA design etc.
+To know more please refer: [Documentation](https://github.com/RISCV-on-Microsemi-FPGA/Documentation)
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch
new file mode 100644
index 000000000..9bc0bf0f3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core16550_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core16550_regs.h
new file mode 100644
index 000000000..0b921ce74
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core16550_regs.h
@@ -0,0 +1,582 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * IP core registers definitions. This file contains the definitions required
+ * for accessing the IP core through the hardware abstraction layer (HAL).
+ * This file was automatically generated, using "get_header.exe" version 0.4.0,
+ * from the IP-XACT description for:
+ *
+ * Core16550 version: 2.0.0
+ *
+ * SVN $Revision: 7963 $
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $
+ *
+ *******************************************************************************/
+#ifndef CORE_16550_REGISTERS_H_
+#define CORE_16550_REGISTERS_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * RBR register:
+ *------------------------------------------------------------------------------
+ * Receive Buffer Register
+ */
+#define RBR_REG_OFFSET 0x00U
+
+/*******************************************************************************
+ * THR register:
+ *------------------------------------------------------------------------------
+ * Transmit Holding Register
+ */
+#define THR_REG_OFFSET 0x00U
+
+/*******************************************************************************
+ * DLR register:
+ *------------------------------------------------------------------------------
+ * Divisor Latch(LSB) Register
+ */
+#define DLR_REG_OFFSET 0x00U
+
+/*******************************************************************************
+ * DMR register:
+ *------------------------------------------------------------------------------
+ * Divisor Latch(MSB) Register
+ */
+#define DMR_REG_OFFSET 0x04U
+
+/*******************************************************************************
+ * IER register:
+ *------------------------------------------------------------------------------
+ * Interrupt Enable Register
+ */
+#define IER_REG_OFFSET 0x04U
+
+/*------------------------------------------------------------------------------
+ * IER_ERBFI:
+ * ERBFI field of register IER.
+ *------------------------------------------------------------------------------
+ * Enables Received Data Available Interrupt. 0 - Disabled; 1 - Enabled
+ */
+#define IER_ERBFI_OFFSET 0x04U
+#define IER_ERBFI_MASK 0x01U
+#define IER_ERBFI_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * IER_ETBEI:
+ * ETBEI field of register IER.
+ *------------------------------------------------------------------------------
+ * Enables the Transmitter Holding Register Empty Interrupt. 0 - Disabled; 1 -
+ * Enabled
+ */
+#define IER_ETBEI_OFFSET 0x04U
+#define IER_ETBEI_MASK 0x02U
+#define IER_ETBEI_SHIFT 1U
+
+/*------------------------------------------------------------------------------
+ * IER_ELSI:
+ * ELSI field of register IER.
+ *------------------------------------------------------------------------------
+ * Enables the Receiver Line Status Interrupt. 0 - Disabled; 1 - Enabled
+ */
+#define IER_ELSI_OFFSET 0x04U
+#define IER_ELSI_MASK 0x04U
+#define IER_ELSI_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * IER_EDSSI:
+ * EDSSI field of register IER.
+ *------------------------------------------------------------------------------
+ * Enables the Modem Status Interrupt 0 - Disabled; 1 - Enabled
+ */
+#define IER_EDSSI_OFFSET 0x04U
+#define IER_EDSSI_MASK 0x08U
+#define IER_EDSSI_SHIFT 3U
+
+/*******************************************************************************
+ * IIR register:
+ *------------------------------------------------------------------------------
+ * Interrupt Identification
+ */
+#define IIR_REG_OFFSET 0x08U
+
+/*------------------------------------------------------------------------------
+ * IIR_IIR:
+ * IIR field of register IIR.
+ *------------------------------------------------------------------------------
+ * Interrupt Identification bits.
+ */
+#define IIR_IIR_OFFSET 0x08U
+#define IIR_IIR_MASK 0x0FU
+#define IIR_IIR_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * IIR_IIR:
+ * IIR field of register IIR.
+ *------------------------------------------------------------------------------
+ * Interrupt Identification bits.
+ */
+
+/*------------------------------------------------------------------------------
+ * IIR_Mode:
+ * Mode field of register IIR.
+ *------------------------------------------------------------------------------
+ * 11 - FIFO mode
+ */
+#define IIR_MODE_OFFSET 0x08U
+#define IIR_MODE_MASK 0xC0U
+#define IIR_MODE_SHIFT 6U
+
+/*******************************************************************************
+ * FCR register:
+ *------------------------------------------------------------------------------
+ * FIFO Control Register
+ */
+#define FCR_REG_OFFSET 0x08
+
+/*------------------------------------------------------------------------------
+ * FCR_Bit0:
+ * Bit0 field of register FCR.
+ *------------------------------------------------------------------------------
+ * This bit enables both the TX and RX FIFOs.
+ */
+#define FCR_BIT0_OFFSET 0x08U
+#define FCR_BIT0_MASK 0x01U
+#define FCR_BIT0_SHIFT 0U
+
+#define FCR_ENABLE_OFFSET 0x08U
+#define FCR_ENABLE_MASK 0x01U
+#define FCR_ENABLE_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * FCR_Bit1:
+ * Bit1 field of register FCR.
+ *------------------------------------------------------------------------------
+ * Clears all bytes in the RX FIFO and resets its counter logic. The shift
+ * register is not cleared. 0 - Disabled; 1 - Enabled
+ */
+#define FCR_BIT1_OFFSET 0x08U
+#define FCR_BIT1_MASK 0x02U
+#define FCR_BIT1_SHIFT 1U
+
+#define FCR_CLEAR_RX_OFFSET 0x08U
+#define FCR_CLEAR_RX_MASK 0x02U
+#define FCR_CLEAR_RX_SHIFT 1U
+
+/*------------------------------------------------------------------------------
+ * FCR_Bit2:
+ * Bit2 field of register FCR.
+ *------------------------------------------------------------------------------
+ * Clears all bytes in the TX FIFO and resets its counter logic. The shift
+ * register is not cleared. 0 - Disabled; 1 - Enabled
+ */
+#define FCR_BIT2_OFFSET 0x08U
+#define FCR_BIT2_MASK 0x04U
+#define FCR_BIT2_SHIFT 2U
+
+#define FCR_CLEAR_TX_OFFSET 0x08U
+#define FCR_CLEAR_TX_MASK 0x04U
+#define FCR_CLEAR_TX_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * FCR_Bit3:
+ * Bit3 field of register FCR.
+ *------------------------------------------------------------------------------
+ * Enables RXRDYN and TXRDYN pins when set to 1. Otherwise, they are disabled.
+ */
+#define FCR_BIT3_OFFSET 0x08U
+#define FCR_BIT3_MASK 0x08U
+#define FCR_BIT3_SHIFT 3U
+
+#define FCR_RDYN_EN_OFFSET 0x08U
+#define FCR_RDYN_EN_MASK 0x08U
+#define FCR_RDYN_EN_SHIFT 3U
+
+/*------------------------------------------------------------------------------
+ * FCR_Bit6:
+ * Bit6 field of register FCR.
+ *------------------------------------------------------------------------------
+ * These bits are used to set the trigger level for the RX FIFO interrupt. RX
+ * FIFO Trigger Level: 0 - 1; 1 - 4; 2 - 8; 3 - 14
+ */
+#define FCR_BIT6_OFFSET 0x08U
+#define FCR_BIT6_MASK 0xC0U
+#define FCR_BIT6_SHIFT 6U
+
+#define FCR_TRIG_LEVEL_OFFSET 0x08U
+#define FCR_TRIG_LEVEL_MASK 0xC0U
+#define FCR_TRIG_LEVEL_SHIFT 6U
+
+/*******************************************************************************
+ * LCR register:
+ *------------------------------------------------------------------------------
+ * Line Control Register
+ */
+#define LCR_REG_OFFSET 0x0CU
+
+/*------------------------------------------------------------------------------
+ * LCR_WLS:
+ * WLS field of register LCR.
+ *------------------------------------------------------------------------------
+ * Word Length Select: 00 - 5 bits; 01 - 6 bits; 10 - 7 bits; 11 - 8 bits
+ */
+#define LCR_WLS_OFFSET 0x0CU
+#define LCR_WLS_MASK 0x03U
+#define LCR_WLS_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * LCR_STB:
+ * STB field of register LCR.
+ *------------------------------------------------------------------------------
+ * Number of Stop Bits: 0 - 1 stop bit; 1 - 1½ stop bits when WLS = 00, 2 stop
+ * bits in other cases
+ */
+#define LCR_STB_OFFSET 0x0CU
+#define LCR_STB_MASK 0x04U
+#define LCR_STB_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * LCR_PEN:
+ * PEN field of register LCR.
+ *------------------------------------------------------------------------------
+ * Parity Enable 0 - Disabled; 1 - Enabled. Parity is added in transmission and
+ * checked in receiving.
+ */
+#define LCR_PEN_OFFSET 0x0CU
+#define LCR_PEN_MASK 0x08U
+#define LCR_PEN_SHIFT 3U
+
+/*------------------------------------------------------------------------------
+ * LCR_EPS:
+ * EPS field of register LCR.
+ *------------------------------------------------------------------------------
+ * Even Parity Select 0 - Odd parity; 1 - Even parity
+ */
+#define LCR_EPS_OFFSET 0x0CU
+#define LCR_EPS_MASK 0x10U
+#define LCR_EPS_SHIFT 4U
+
+/*------------------------------------------------------------------------------
+ * LCR_SP:
+ * SP field of register LCR.
+ *------------------------------------------------------------------------------
+ * Stick Parity 0 - Disabled; 1 - Enabled When stick parity is enabled, it
+ * works as follows: Bits 4..3, 11 - 0 will be sent as a parity bit, and
+ * checked in receiving. 01 - 1 will be sent as a parity bit, and checked in
+ * receiving.
+ */
+#define LCR_SP_OFFSET 0x0CU
+#define LCR_SP_MASK 0x20U
+#define LCR_SP_SHIFT 5U
+
+/*------------------------------------------------------------------------------
+ * LCR_SB:
+ * SB field of register LCR.
+ *------------------------------------------------------------------------------
+ * Set Break 0 - Disabled 1 - Set break. SOUT is forced to 0. This does not
+ * have any effect on transmitter logic. The break is disabled by setting the
+ * bit to 0.
+ */
+#define LCR_SB_OFFSET 0x0CU
+#define LCR_SB_MASK 0x40U
+#define LCR_SB_SHIFT 6U
+
+/*------------------------------------------------------------------------------
+ * LCR_DLAB:
+ * DLAB field of register LCR.
+ *------------------------------------------------------------------------------
+ * Divisor Latch Access Bit 0 - Disabled. Normal addressing mode in use 1 -
+ * Enabled. Enables access to the Divisor Latch registers during read or write
+ * operation to addresses 0 and 1.
+ */
+#define LCR_DLAB_OFFSET 0x0CU
+#define LCR_DLAB_MASK 0x80U
+#define LCR_DLAB_SHIFT 7U
+
+/*******************************************************************************
+ * MCR register:
+ *------------------------------------------------------------------------------
+ * Modem Control Register
+ */
+#define MCR_REG_OFFSET 0x10U
+
+/*------------------------------------------------------------------------------
+ * MCR_DTR:
+ * DTR field of register MCR.
+ *------------------------------------------------------------------------------
+ * Controls the Data Terminal Ready (DTRn) output. 0 - DTRn <= 1; 1 - DTRn <= 0
+ */
+#define MCR_DTR_OFFSET 0x10U
+#define MCR_DTR_MASK 0x01U
+#define MCR_DTR_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * MCR_RTS:
+ * RTS field of register MCR.
+ *------------------------------------------------------------------------------
+ * Controls the Request to Send (RTSn) output. 0 - RTSn <= 1; 1 - RTSn <= 0
+ */
+#define MCR_RTS_OFFSET 0x10U
+#define MCR_RTS_MASK 0x02U
+#define MCR_RTS_SHIFT 1U
+
+/*------------------------------------------------------------------------------
+ * MCR_Out1:
+ * Out1 field of register MCR.
+ *------------------------------------------------------------------------------
+ * Controls the Output1 (OUT1n) signal. 0 - OUT1n <= 1; 1 - OUT1n <= 0
+ */
+#define MCR_OUT1_OFFSET 0x10U
+#define MCR_OUT1_MASK 0x04U
+#define MCR_OUT1_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * MCR_Out2:
+ * Out2 field of register MCR.
+ *------------------------------------------------------------------------------
+ * Controls the Output2 (OUT2n) signal. 0 - OUT2n <=1; 1 - OUT2n <=0
+ */
+#define MCR_OUT2_OFFSET 0x10U
+#define MCR_OUT2_MASK 0x08U
+#define MCR_OUT2_SHIFT 3U
+
+/*------------------------------------------------------------------------------
+ * MCR_Loop:
+ * Loop field of register MCR.
+ *------------------------------------------------------------------------------
+ * Loop enable bit 0 - Disabled; 1 - Enabled. The following happens in loop
+ * mode: SOUT is set to 1. The SIN, DSRn, CTSn, RIn, and DCDn inputs are
+ * disconnected. The output of the Transmitter Shift Register is looped back
+ * into the Receiver Shift Register. The modem control outputs (DTRn, RTSn,
+ * OUT1n, and OUT2n) are connected internally to the modem control inputs, and
+ * the modem control output pins are set at 1. In loopback mode, the
+ * transmitted data is immediately received, allowing the CPU to check the
+ * operation of the UART. The interrupts are operating in loop mode.
+ */
+#define MCR_LOOP_OFFSET 0x10U
+#define MCR_LOOP_MASK 0x10U
+#define MCR_LOOP_SHIFT 4U
+
+/*******************************************************************************
+ * LSR register:
+ *------------------------------------------------------------------------------
+ * Line Status Register
+ */
+#define LSR_REG_OFFSET 0x14U
+
+/*------------------------------------------------------------------------------
+ * LSR_DR:
+ * DR field of register LSR.
+ *------------------------------------------------------------------------------
+ * Data Ready indicator 1 when a data byte has been received and stored in the
+ * FIFO. DR is cleared to 0 when the CPU reads the data from the FIFO.
+ */
+#define LSR_DR_OFFSET 0x14U
+#define LSR_DR_MASK 0x01U
+#define LSR_DR_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * LSR_OE:
+ * OE field of register LSR.
+ *------------------------------------------------------------------------------
+ * Overrun Error indicator Indicates that the new byte was received before the
+ * CPU read the byte from the receive buffer, and that the earlier data byte
+ * was destroyed. OE is cleared when the CPU reads the Line Status Register. If
+ * the data continues to fill the FIFO beyond the trigger level, an overrun
+ * error will occur once the FIFO is full and the next character has been
+ * completely received in the shift register. The character in the shift
+ * register is overwritten, but it is not transferred to the FIFO.
+ */
+#define LSR_OE_OFFSET 0x14U
+#define LSR_OE_MASK 0x02U
+#define LSR_OE_SHIFT 1U
+
+/*------------------------------------------------------------------------------
+ * LSR_PE:
+ * PE field of register LSR.
+ *------------------------------------------------------------------------------
+ * Parity Error indicator Indicates that the received byte had a parity error.
+ * PE is cleared when the CPU reads the Line Status Register. This error is
+ * revealed to the CPU when its associated character is at the top of the FIFO.
+ */
+#define LSR_PE_OFFSET 0x14U
+#define LSR_PE_MASK 0x04U
+#define LSR_PE_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * LSR_FE:
+ * FE field of register LSR.
+ *------------------------------------------------------------------------------
+ * Framing Error indicator Indicates that the received byte did not have a
+ * valid Stop bit. FE is cleared when the CPU reads the Line Status Register.
+ * The UART will try to re-synchronize after a framing error. To do this, it
+ * assumes that the framing error was due to the next start bit, so it samples
+ * this start bit twice, and then starts receiving the data. This error is
+ * revealed to the CPU when its associated character is at the top of the FIFO.
+ */
+#define LSR_FE_OFFSET 0x14U
+#define LSR_FE_MASK 0x08U
+#define LSR_FE_SHIFT 3U
+
+/*------------------------------------------------------------------------------
+ * LSR_BI:
+ * BI field of register LSR.
+ *------------------------------------------------------------------------------
+ * Break Interrupt indicator Indicates that the received data is at 0 longer
+ * than a full word transmission time (start bit + data bits + parity + stop
+ * bits). BI is cleared when the CPU reads the Line Status Register. This error
+ * is revealed to the CPU when its associated character is at the top of the
+ * FIFO. When break occurs, only one zero character is loaded into the FIFO.
+ */
+#define LSR_BI_OFFSET 0x14U
+#define LSR_BI_MASK 0x10U
+#define LSR_BI_SHIFT 4U
+
+/*------------------------------------------------------------------------------
+ * LSR_THRE:
+ * THRE field of register LSR.
+ *------------------------------------------------------------------------------
+ * Transmitter Holding Register Empty indicator Indicates that the UART is
+ * ready to transmit a new data byte. THRE causes an interrupt to the CPU when
+ * bit 1 (ETBEI) in the Interrupt Enable Register is 1. This bit is set when
+ * the TX FIFO is empty. It is cleared when at least one byte is written to the
+ * TX FIFO.
+ */
+#define LSR_THRE_OFFSET 0x14U
+#define LSR_THRE_MASK 0x20U
+#define LSR_THRE_SHIFT 5U
+
+/*------------------------------------------------------------------------------
+ * LSR_TEMT:
+ * TEMT field of register LSR.
+ *------------------------------------------------------------------------------
+ * Transmitter Empty indicator This bit is set to 1 when both the transmitter
+ * FIFO and shift registers are empty.
+ */
+#define LSR_TEMT_OFFSET 0x14U
+#define LSR_TEMT_MASK 0x40U
+#define LSR_TEMT_SHIFT 6U
+
+/*------------------------------------------------------------------------------
+ * LSR_FIER:
+ * FIER field of register LSR.
+ *------------------------------------------------------------------------------
+ * This bit is set when there is at least one parity error, framing error, or
+ * break indication in the FIFO. FIER is cleared when the CPU reads the LSR if
+ * there are no subsequent errors in the FIFO.
+ */
+#define LSR_FIER_OFFSET 0x14U
+#define LSR_FIER_MASK 0x80U
+#define LSR_FIER_SHIFT 7U
+
+/*******************************************************************************
+ * MSR register:
+ *------------------------------------------------------------------------------
+ * Modem Status Register
+ */
+#define MSR_REG_OFFSET 0x18U
+
+/*------------------------------------------------------------------------------
+ * MSR_DCTS:
+ * DCTS field of register MSR.
+ *------------------------------------------------------------------------------
+ * Delta Clear to Send indicator. Indicates that the CTSn input has changed
+ * state since the last time it was read by the CPU.
+ */
+#define MSR_DCTS_OFFSET 0x18U
+#define MSR_DCTS_MASK 0x01U
+#define MSR_DCTS_SHIFT 0U
+
+/*------------------------------------------------------------------------------
+ * MSR_DDSR:
+ * DDSR field of register MSR.
+ *------------------------------------------------------------------------------
+ * Delta Data Set Ready indicator Indicates that the DSRn input has changed
+ * state since the last time it was read by the CPU.
+ */
+#define MSR_DDSR_OFFSET 0x18U
+#define MSR_DDSR_MASK 0x02U
+#define MSR_DDSR_SHIFT 1U
+
+/*------------------------------------------------------------------------------
+ * MSR_TERI:
+ * TERI field of register MSR.
+ *------------------------------------------------------------------------------
+ * Trailing Edge of Ring Indicator detector. Indicates that RI input has
+ * changed from 0 to 1.
+ */
+#define MSR_TERI_OFFSET 0x18U
+#define MSR_TERI_MASK 0x04U
+#define MSR_TERI_SHIFT 2U
+
+/*------------------------------------------------------------------------------
+ * MSR_DDCD:
+ * DDCD field of register MSR.
+ *------------------------------------------------------------------------------
+ * Delta Data Carrier Detect indicator Indicates that DCD input has changed
+ * state. NOTE: Whenever bit 0, 1, 2, or 3 is set to 1, a Modem Status
+ * Interrupt is generated.
+ */
+#define MSR_DDCD_OFFSET 0x18U
+#define MSR_DDCD_MASK 0x08U
+#define MSR_DDCD_SHIFT 3U
+
+/*------------------------------------------------------------------------------
+ * MSR_CTS:
+ * CTS field of register MSR.
+ *------------------------------------------------------------------------------
+ * Clear to Send The complement of the CTSn input. When bit 4 of the Modem
+ * Control Register (MCR) is set to 1 (loop), this bit is equivalent to DTR in
+ * the MCR.
+ */
+#define MSR_CTS_OFFSET 0x18U
+#define MSR_CTS_MASK 0x10U
+#define MSR_CTS_SHIFT 4U
+
+/*------------------------------------------------------------------------------
+ * MSR_DSR:
+ * DSR field of register MSR.
+ *------------------------------------------------------------------------------
+ * Data Set Ready The complement of the DSR input. When bit 4 of the MCR is set
+ * to 1 (loop), this bit is equivalent to RTSn in the MCR.
+ */
+#define MSR_DSR_OFFSET 0x18U
+#define MSR_DSR_MASK 0x20U
+#define MSR_DSR_SHIFT 5U
+
+/*------------------------------------------------------------------------------
+ * MSR_RI:
+ * RI field of register MSR.
+ *------------------------------------------------------------------------------
+ * Ring Indicator The complement of the RIn input. When bit 4 of the MCR is set
+ * to 1 (loop), this bit is equivalent to OUT1 in the MCR.
+ */
+#define MSR_RI_OFFSET 0x18U
+#define MSR_RI_MASK 0x40U
+#define MSR_RI_SHIFT 6U
+
+/*------------------------------------------------------------------------------
+ * MSR_DCD:
+ * DCD field of register MSR.
+ *------------------------------------------------------------------------------
+ * Data Carrier Detect The complement of DCDn input. When bit 4 of the MCR is
+ * set to 1 (loop), this bit is equivalent to OUT2 in the MCR.
+ */
+#define MSR_DCD_OFFSET 0x18U
+#define MSR_DCD_MASK 0x80U
+#define MSR_DCD_SHIFT 7U
+
+/*******************************************************************************
+ * SR register:
+ *------------------------------------------------------------------------------
+ * Scratch Register
+ */
+#define SR_REG_OFFSET 0x1CU
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CORE_16550_REGISTERS_H_*/
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.c
new file mode 100644
index 000000000..ca735e63a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.c
@@ -0,0 +1,865 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Core16550 driver implementation. See file "core_16550.h" for a
+ * description of the functions implemented in this file.
+ *
+ * SVN $Revision: 7963 $
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $
+ */
+#include "hal.h"
+#include "core_16550.h"
+#include "core16550_regs.h"
+#include "hal_assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * Definitions for transmitter states
+ */
+#define TX_COMPLETE 0x00U
+
+/*******************************************************************************
+ * Definition for transmitter FIFO size
+ */
+#define TX_FIFO_SIZE 16U
+
+/*******************************************************************************
+ * Default receive interrupt trigger level
+ */
+#define DEFAULT_RX_TRIG_LEVEL ((uint8_t)UART_16550_FIFO_SINGLE_BYTE)
+
+/*******************************************************************************
+ * Receiver error status mask and shift offset
+ */
+#define STATUS_ERROR_MASK ( LSR_OE_MASK | LSR_PE_MASK | \
+ LSR_FE_MASK | LSR_BI_MASK | LSR_FIER_MASK)
+
+/*******************************************************************************
+ * Definitions for invalid parameters with proper type
+ */
+#define INVALID_INTERRUPT 0U
+#define INVALID_IRQ_HANDLER ( (uart_16550_irq_handler_t) 0 )
+
+/*******************************************************************************
+ * Possible values for Interrupt Identification Register Field.
+ */
+#define IIRF_MODEM_STATUS 0x00U
+#define IIRF_THRE 0x02U
+#define IIRF_RX_DATA 0x04U
+#define IIRF_RX_LINE_STATUS 0x06U
+#define IIRF_DATA_TIMEOUT 0x0CU
+
+/*******************************************************************************
+ * Null parameters with appropriate type definitions
+ */
+#define NULL_ADDR ( ( addr_t ) 0 )
+#define NULL_INSTANCE ( ( uart_16550_instance_t * ) 0 )
+#define NULL_BUFF ( ( uint8_t * ) 0 )
+
+/*******************************************************************************
+ * Possible states for different register bit fields
+ */
+enum {
+ DISABLE = 0U,
+ ENABLE = 1U
+};
+
+/*******************************************************************************
+ * Static function declarations
+ */
+static void default_tx_handler(uart_16550_instance_t * this_uart);
+
+/*******************************************************************************
+ * Public function definitions
+ */
+
+/***************************************************************************//**
+ * UART_16550_init.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_init
+(
+ uart_16550_instance_t* this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+)
+{
+#ifndef NDEBUG
+ uint8_t dbg1;
+ uint8_t dbg2;
+#endif
+ uint8_t fifo_config;
+ uint8_t temp;
+
+ HAL_ASSERT( base_addr != NULL_ADDR );
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+
+ if( ( base_addr != NULL_ADDR ) && ( this_uart != NULL_INSTANCE ) )
+ {
+ /* disable interrupts */
+ HAL_set_8bit_reg(base_addr, IER, DISABLE);
+
+ /* reset divisor latch */
+ HAL_set_8bit_reg_field(base_addr, LCR_DLAB, ENABLE);
+#ifndef NDEBUG
+ dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );
+ HAL_ASSERT( dbg1 == ENABLE );
+#endif
+ /* MSB of baud value */
+ temp = (uint8_t)(baud_value >> 8);
+ HAL_set_8bit_reg(base_addr, DMR, temp );
+ /* LSB of baud value */
+ HAL_set_8bit_reg(base_addr, DLR, ( (uint8_t)baud_value ) );
+#ifndef NDEBUG
+ dbg1 = HAL_get_8bit_reg(base_addr, DMR );
+ dbg2 = HAL_get_8bit_reg(base_addr, DLR );
+ HAL_ASSERT( ( ( ( (uint16_t) dbg1 ) << 8 ) | dbg2 ) == baud_value );
+#endif
+ /* reset divisor latch */
+ HAL_set_8bit_reg_field(base_addr, LCR_DLAB, DISABLE);
+#ifndef NDEBUG
+ dbg1 = HAL_get_8bit_reg_field(base_addr, LCR_DLAB );
+ HAL_ASSERT( dbg1 == DISABLE );
+#endif
+ /* set the line control register (bit length, stop bits, parity) */
+ HAL_set_8bit_reg( base_addr, LCR, line_config );
+#ifndef NDEBUG
+ dbg1 = HAL_get_8bit_reg(base_addr, LCR );
+ HAL_ASSERT( dbg1 == line_config)
+#endif
+ /* Enable and configure the RX and TX FIFOs. */
+ fifo_config = ((uint8_t)(DEFAULT_RX_TRIG_LEVEL << FCR_TRIG_LEVEL_SHIFT) |
+ FCR_RDYN_EN_MASK | FCR_CLEAR_RX_MASK |
+ FCR_CLEAR_TX_MASK | FCR_ENABLE_MASK );
+ HAL_set_8bit_reg( base_addr, FCR, fifo_config );
+
+ /* disable loopback */
+ HAL_set_8bit_reg_field( base_addr, MCR_LOOP, DISABLE );
+#ifndef NDEBUG
+ dbg1 = HAL_get_8bit_reg_field(base_addr, MCR_LOOP);
+ HAL_ASSERT( dbg1 == DISABLE );
+#endif
+
+ /* Instance setup */
+ this_uart->base_address = base_addr;
+ this_uart->tx_buffer = NULL_BUFF;
+ this_uart->tx_buff_size = TX_COMPLETE;
+ this_uart->tx_idx = 0U;
+ this_uart->tx_handler = default_tx_handler;
+
+ this_uart->rx_handler = ( (uart_16550_irq_handler_t) 0 );
+ this_uart->linests_handler = ( (uart_16550_irq_handler_t) 0 );
+ this_uart->modemsts_handler = ( (uart_16550_irq_handler_t) 0 );
+ this_uart->status = 0U;
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_polled_tx.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_polled_tx
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+)
+{
+ uint32_t char_idx = 0U;
+ uint32_t size_sent;
+ uint8_t status;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+ HAL_ASSERT( pbuff != NULL_BUFF );
+ HAL_ASSERT( tx_size > 0U );
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( pbuff != NULL_BUFF ) &&
+ ( 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 = HAL_get_8bit_reg( this_uart->base_address, LSR );
+ this_uart->status |= status;
+
+ /* Check if TX FIFO is empty. */
+ if( status & LSR_THRE_MASK )
+ {
+ 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. */
+ HAL_set_8bit_reg( this_uart->base_address, THR,
+ (uint_fast8_t)pbuff[char_idx++]);
+ }
+
+ /* Calculate the number of untransmitted bytes remaining. */
+ tx_size -= size_sent;
+ }
+ } while ( tx_size );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_polled_tx_string.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_polled_tx_string
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * p_sz_string
+)
+{
+ uint32_t char_idx = 0U;
+ uint32_t fill_size;
+ uint_fast8_t data_byte;
+ uint8_t status;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+ HAL_ASSERT( p_sz_string != NULL_BUFF );
+
+ if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFF ) )
+ {
+ char_idx = 0U;
+
+ /* Get the first data byte from the input buffer */
+ data_byte = (uint_fast8_t)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 = HAL_get_8bit_reg( this_uart->base_address,LSR);
+ this_uart->status |= status;
+ } while ( !( status & LSR_THRE_MASK ) );
+
+ /* 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 */
+ HAL_set_8bit_reg( this_uart->base_address, THR, data_byte );
+ ++fill_size;
+ char_idx++;
+ /* Get the next data byte from the input buffer */
+ data_byte = (uint_fast8_t)p_sz_string[char_idx];
+ }
+ }
+ }
+}
+
+
+/***************************************************************************//**
+ * UART_16550_irq_tx.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_irq_tx
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( pbuff != NULL_BUFF )
+ HAL_ASSERT( tx_size > 0U )
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( pbuff != NULL_BUFF ) &&
+ ( tx_size > 0U ) )
+ {
+ /*Initialize the UART instance with
+ parameters required for transmission.*/
+ this_uart->tx_buffer = pbuff;
+ this_uart->tx_buff_size = tx_size;
+ /* char_idx; */
+ this_uart->tx_idx = 0U;
+ /* assign handler for default data transmission */
+ this_uart->tx_handler = default_tx_handler;
+
+ /* enables TX interrupt */
+ HAL_set_8bit_reg_field(this_uart->base_address, IER_ETBEI, ENABLE);
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_tx_complete.
+ * See core_16550.h for details of how to use this function.
+ */
+int8_t
+UART_16550_tx_complete
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ int8_t returnvalue = 0;
+ uint8_t status = 0U;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+
+ if( this_uart != NULL_INSTANCE )
+ {
+ status = HAL_get_8bit_reg(this_uart->base_address,LSR);
+ this_uart->status |= status;
+
+ if( ( this_uart->tx_buff_size == TX_COMPLETE ) &&
+ ( status & LSR_TEMT_MASK ) )
+ {
+ returnvalue = (int8_t)1;
+ }
+ }
+ return returnvalue;
+}
+
+
+/***************************************************************************//**
+ * UART_16550_get_rx.
+ * See core_16550.h for details of how to use this function.
+ */
+size_t
+UART_16550_get_rx
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t * rx_buff,
+ size_t buff_size
+)
+{
+ uint8_t status;
+ size_t rx_size = 0U;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( rx_buff != (uint8_t *)0 )
+ HAL_ASSERT( buff_size > 0U )
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( rx_buff != (uint8_t *)0 ) &&
+ ( buff_size > 0U ) )
+ {
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );
+ this_uart->status |= status;
+ while ( ((status & LSR_DR_MASK) != 0U) && ( rx_size < buff_size ) )
+ {
+ rx_buff[rx_size] = HAL_get_8bit_reg( this_uart->base_address, RBR );
+ rx_size++;
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );
+ this_uart->status |= status;
+ }
+ }
+ return rx_size;
+}
+
+/***************************************************************************//**
+ * UART_16550_isr.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_isr
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ uint8_t iirf;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+
+ if(this_uart != NULL_INSTANCE )
+ {
+ iirf = HAL_get_8bit_reg_field( this_uart->base_address, IIR_IIR );
+
+ switch ( iirf )
+ {
+ /* Modem status interrupt */
+ case IIRF_MODEM_STATUS:
+ {
+ if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )
+ {
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->modemsts_handler );
+ if( INVALID_IRQ_HANDLER != this_uart->modemsts_handler )
+ {
+ (*(this_uart->modemsts_handler))(this_uart);
+ }
+ }
+ }
+ break;
+ /* Transmitter Holding Register Empty interrupt */
+ case IIRF_THRE:
+ {
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->tx_handler );
+ if ( INVALID_IRQ_HANDLER != this_uart->tx_handler )
+ {
+ (*(this_uart->tx_handler))(this_uart);
+ }
+ }
+ break;
+ /* Received Data Available interrupt */
+ case IIRF_RX_DATA:
+ case IIRF_DATA_TIMEOUT:
+ {
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->rx_handler );
+ if ( INVALID_IRQ_HANDLER != this_uart->rx_handler )
+ {
+ (*(this_uart->rx_handler))(this_uart);
+ }
+ }
+ break;
+ /* Line status interrupt */
+ case IIRF_RX_LINE_STATUS:
+ {
+ HAL_ASSERT( INVALID_IRQ_HANDLER != this_uart->linests_handler );
+ if ( INVALID_IRQ_HANDLER != this_uart->linests_handler )
+ {
+ (*(this_uart->linests_handler))(this_uart);
+ }
+ }
+ break;
+ /* Unidentified interrupt */
+ default:
+ {
+ HAL_ASSERT( INVALID_INTERRUPT )
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_set_rx_handler.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_set_rx_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler,
+ uart_16550_rx_trig_level_t trigger_level
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
+ HAL_ASSERT( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL)
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( handler != INVALID_IRQ_HANDLER) &&
+ ( trigger_level < UART_16550_FIFO_INVALID_TRIG_LEVEL) )
+ {
+ this_uart->rx_handler = handler;
+
+ /* Set the receive interrupt trigger level. */
+ HAL_set_8bit_reg_field( this_uart->base_address,
+ FCR_TRIG_LEVEL, trigger_level );
+
+ /* Enable receive interrupt. */
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ERBFI, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_set_loopback.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_set_loopback
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_loopback_t loopback
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+ HAL_ASSERT( loopback < UART_16550_INVALID_LOOPBACK );
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( loopback < UART_16550_INVALID_LOOPBACK ) )
+ {
+ if ( loopback == UART_16550_LOOPBACK_OFF )
+ {
+ HAL_set_8bit_reg_field( this_uart->base_address,
+ MCR_LOOP,
+ DISABLE );
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_uart->base_address,
+ MCR_LOOP,
+ ENABLE );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_get_rx_status.
+ * See core_16550.h for details of how to use this function.
+ */
+uint8_t
+UART_16550_get_rx_status
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ uint8_t status = UART_16550_INVALID_PARAM;
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+
+ if( ( this_uart != NULL_INSTANCE ) )
+ {
+ /*
+ * 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 |= HAL_get_8bit_reg( this_uart->base_address, LSR );
+ status = ( this_uart->status & STATUS_ERROR_MASK );
+ /*
+ * Clear the sticky status for this instance.
+ */
+ this_uart->status = (uint8_t)0;
+ }
+ return status;
+}
+
+/***************************************************************************//**
+ * UART_16550_get_modem_status.
+ * See core_16550.h for details of how to use this function.
+ */
+uint8_t
+UART_16550_get_modem_status
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ uint8_t status = UART_16550_NO_ERROR;
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+
+ if( ( this_uart != NULL_INSTANCE ) )
+ {
+ /*
+ * Extract UART error 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 = HAL_get_8bit_reg( this_uart->base_address, MSR );
+ }
+ return status;
+}
+
+/***************************************************************************//**
+ * Default TX interrupt handler to automatically transmit data from
+ * user assgined TX buffer.
+ */
+static void
+default_tx_handler
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ uint8_t status;
+
+ HAL_ASSERT( NULL_INSTANCE != this_uart )
+
+ if ( this_uart != NULL_INSTANCE )
+ {
+ HAL_ASSERT( NULL_BUFF != this_uart->tx_buffer )
+ HAL_ASSERT( 0U != this_uart->tx_buff_size )
+
+ if ( ( this_uart->tx_buffer != NULL_BUFF ) &&
+ ( 0U != this_uart->tx_buff_size ) )
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = HAL_get_8bit_reg( this_uart->base_address,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 & LSR_THRE_MASK )
+ {
+ uint32_t size_sent = 0U;
+ 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 ( size_sent = 0U; size_sent < fill_size; ++size_sent )
+ {
+ /* Send next character in the buffer. */
+ HAL_set_8bit_reg( this_uart->base_address, THR,
+ (uint_fast8_t)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 */
+ HAL_set_8bit_reg_field( this_uart->base_address,
+ IER_ETBEI, DISABLE);
+ }
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_enable_irq.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_enable_irq
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t irq_mask
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+
+ if( this_uart != NULL_INSTANCE )
+ {
+ /* 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
+ */
+ /* read present interrupts for enabled ones*/
+ irq_mask |= HAL_get_8bit_reg( this_uart->base_address, IER );
+ /* Enable interrupts */
+ HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_disable_irq.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_disable_irq
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t irq_mask
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+
+ if( this_uart != NULL_INSTANCE )
+ {
+ /* 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
+ */
+ /* read present interrupts for enabled ones */
+ irq_mask = (( (uint8_t)~irq_mask ) &
+ HAL_get_8bit_reg( this_uart->base_address, IER ));
+ /* Disable interrupts */
+ HAL_set_8bit_reg( this_uart->base_address, IER, irq_mask );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_set_rxstatus_handler.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_set_rxstatus_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( handler != INVALID_IRQ_HANDLER) )
+ {
+ this_uart->linests_handler = handler;
+ /* Enable receiver line status interrupt. */
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ELSI, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_set_tx_handler.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_set_tx_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( handler != INVALID_IRQ_HANDLER) )
+ {
+ this_uart->tx_handler = handler;
+
+ /* Make TX buffer info invalid */
+ this_uart->tx_buffer = NULL_BUFF;
+ this_uart->tx_buff_size = 0U;
+
+ /* Enable transmitter holding register Empty interrupt. */
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_ETBEI, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_set_modemstatus_handler.
+ * See core_16550.h for details of how to use this function.
+ */
+void
+UART_16550_set_modemstatus_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+)
+{
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( handler != INVALID_IRQ_HANDLER)
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( handler != INVALID_IRQ_HANDLER) )
+ {
+ this_uart->modemsts_handler = handler;
+ /* Enable modem status interrupt. */
+ HAL_set_8bit_reg_field( this_uart->base_address, IER_EDSSI, ENABLE );
+ }
+}
+
+/***************************************************************************//**
+ * UART_16550_fill_tx_fifo.
+ * See core_16550.h for details of how to use this function.
+ */
+size_t
+UART_16550_fill_tx_fifo
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ uint8_t status;
+ size_t size_sent = 0U;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( tx_buffer != NULL_BUFF )
+ HAL_ASSERT( tx_size > 0U )
+
+ /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
+ * buffer has been written. */
+ if( (this_uart != NULL_INSTANCE) &&
+ (tx_buffer != NULL_BUFF) &&
+ (tx_size > 0U) )
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = HAL_get_8bit_reg( this_uart->base_address, LSR );
+ this_uart->status |= status;
+
+ /* Check if TX FIFO is empty. */
+ if( status & LSR_THRE_MASK )
+ {
+ 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. */
+ HAL_set_8bit_reg( this_uart->base_address, THR,
+ (uint_fast8_t)tx_buffer[size_sent]);
+ }
+ }
+ }
+ return size_sent;
+}
+
+/***************************************************************************//**
+ * UART_16550_get_tx_status.
+ * See core_16550.h for details of how to use this function.
+ */
+uint8_t
+UART_16550_get_tx_status
+(
+ uart_16550_instance_t * this_uart
+)
+{
+ uint8_t status = UART_16550_TX_BUSY;
+ HAL_ASSERT( this_uart != NULL_INSTANCE );
+
+ if( ( this_uart != NULL_INSTANCE ) )
+ {
+ /* Read the Line Status Register and update the sticky record. */
+ status = HAL_get_8bit_reg( this_uart->base_address, 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 &= ( LSR_THRE_MASK | LSR_TEMT_MASK );
+ }
+ return status;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.h
new file mode 100644
index 000000000..98b1f16ea
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/Core16550/core_16550.h
@@ -0,0 +1,1264 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * This file contains the application programming interface for the Core16550
+ * bare metal driver.
+ *
+ * SVN $Revision: 7963 $
+ * SVN $Date: 2015-10-09 17:58:21 +0530 (Fri, 09 Oct 2015) $
+ */
+/*=========================================================================*//**
+ @mainpage Core16550 Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The Core16550 is an implementation of the Universal Asynchronous
+ Receiver/Transmitter aimed at complete compliance to standard 16550 UART.
+ The Core16550 bare metal software driver is designed for use in systems
+ with no operating system.
+
+ The Core16550 driver provides functions for polled and interrupt driven
+ transmitting and receiving. It also provides functions for reading the
+ values from different status registers, enabling and disabling interrupts
+ at Core16550 level. The Core16550 driver is provided as C source code.
+
+ @section driver_configuration Driver Configuration
+ Your application software should configure the Core16550 driver through
+ calls to the UART_16550_init() function for each Core16550 instance in
+ the hardware design. The configuration parameters include the Core16550
+ hardware instance base address and other runtime parameters, such as baud
+ value, bit width, and parity.
+
+ No Core16550 hardware configuration parameters are needed by the driver,
+ apart from the Core16550 hardware instance base address. Hence, no
+ additional configuration files are required to use the driver.
+
+ @section theory_op Theory of Operation
+ The Core16550 software driver is designed to allow the control of multiple
+ instances of Core16550. Each instance of Core16550 in the hardware design
+ is associated with a single instance of the uart_16550_instance_t structure
+ in the software. You need to allocate memory for one unique
+ uart_16550_instance_t structure instance for each Core16550 hardware instance.
+ The contents of these data structures are initialized during calls to
+ function UART_16550_init(). A pointer to the structure is passed to
+ subsequent driver functions in order to identify the Core16550 hardware
+ instance you wish to perform the requested operation on.
+
+ Note: Do not attempt to directly manipulate the content of
+ uart_16550_instance_t structures. This structure is only intended to be
+ modified by the driver function.
+
+ Initialization
+ The Core16550 driver is initialized through a call to the UART_16550_init()
+ function. This function takes the UART’s configuration as parameters.
+ The UART_16550_init() function must be called before any other Core16550
+ driver functions can be called.
+
+ Polled Transmission and Reception
+ The driver can be used to transmit and receive data once initialized. Polled
+ operations where the driver constantly polls the state of the UART registers
+ in order to control data transmit or data receive are performed using these
+ functions:
+ • UART_16550_polled_tx()
+ • UART_16550_polled_tx_string
+ • UART_16550_fill_tx_fifo()
+ • UART_16550_get_rx()
+
+ Data is transmitted using the UART_16550_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 Core16550 hardware. Data received by the
+ Core16550 hardware can be read by the UART_16550_get_rx() function.
+
+ The UART_16550_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
+ Core16550 hardware.
+
+ The UART_16550_fill_tx_fifo() function fills the Core16550 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
+ UART_16550_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 controlled UART operations
+ are performed using these functions:
+ • UART_16550_isr()
+ • UART_16550_irq_tx()
+ • UART_16550_tx_complete()
+ • UART_16550_set_tx_handler()
+ • UART_16550_set_rx_handler()
+ • UART_16550_set_rxstatus_handler()
+ • UART_16550_set_modemstatus_handler()
+ • UART_16550_enable_irq()
+ • UART_16550_disable_irq()
+
+ Interrupt Handlers
+ The UART_16550_isr() function is the top level interrupt handler function for
+ the Core16550 driver. You must call it from the system level
+ (CoreInterrupt and NVIC level) interrupt service routine (ISR) assigned to the
+ interrupt triggered by the Core16550 INTR signal. The UART_16550_isr() function
+ identifies the source of the Core16550 interrupt and calls the corresponding
+ handler function previously registered with the driver through calls to the
+ UART_16550_set_rx_handler(), UART_16550_set_tx_handler(),
+ UART_16550_set_rxstatus_handler(), and UART_16550_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.
+ The UART_16550_enable_irq() and UART_16550_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
+ Core16550 level.
+
+ Transmitting Data
+ Interrupt-driven transmit is initiated by a call to UART_16550_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 UART_16550_tx_complete() function. The UART_16550_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 UART_16550_set_tx_handler() function to assign an
+ alternative handler to the THRE interrupt. In this case, you must not use the
+ UART_16550_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
+ UART_16550_fill_tx_fifo() function to transfer the data to the UART.
+
+ Receiving Data
+ Interrupt-driven receive is performed by first calling UART_16550_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 UART_16550_get_rx() function to actually read the
+ received data.
+
+ UART Status
+ The function UART_16550_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 UART_16550_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 UART_16550_get_modem_status() is used to read the modem status flags.
+ This function returns the current value of the modem status register.
+
+ Loopback
+ The function UART_16550_set_loopback() is used to enable or disable loopback
+ between Tx and Rx lines internal to Core16550.
+*//*=========================================================================*/
+#ifndef __CORE_16550_H
+#define __CORE_16550_H 1
+
+#include "cpu_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * 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
+ * UART_16550_get_rx_status() function to find out if any errors occurred
+ * while receiving data.
+ */
+#define UART_16550_NO_ERROR ( (uint8_t) 0x00 )
+#define UART_16550_OVERRUN_ERROR ( (uint8_t) 0x02 )
+#define UART_16550_PARITY_ERROR ( (uint8_t) 0x04 )
+#define UART_16550_FRAMING_ERROR ( (uint8_t) 0x08 )
+#define UART_16550_BREAK_ERROR ( (uint8_t) 0x10 )
+#define UART_16550_FIFO_ERROR ( (uint8_t) 0x80 )
+#define UART_16550_INVALID_PARAM ( (uint8_t) 0xFF )
+
+/***************************************************************************//**
+ * Modem Status
+ * The following defines are used to determine the modem status. These bit
+ * mask constants are used with the return value of the
+ * UART_16550_get_modem_status() function to find out the modem status of
+ * the UART.
+ */
+#define UART_16550_DCTS ( (uint8_t) 0x01 )
+#define UART_16550_DDSR ( (uint8_t) 0x02 )
+#define UART_16550_TERI ( (uint8_t) 0x04 )
+#define UART_16550_DDCD ( (uint8_t) 0x08 )
+#define UART_16550_CTS ( (uint8_t) 0x10 )
+#define UART_16550_DSR ( (uint8_t) 0x20 )
+#define UART_16550_RI ( (uint8_t) 0x40 )
+#define UART_16550_DCD ( (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
+ * UART_16550_get_tx_status() function to find out the status of the
+ * transmitter.
+ */
+#define UART_16550_TX_BUSY ( (uint8_t) 0x00 )
+#define UART_16550_THRE ( (uint8_t) 0x20 )
+#define UART_16550_TEMT ( (uint8_t) 0x40 )
+
+/***************************************************************************//**
+ * Core16550 Interrupts
+ * The following defines are used to enable and disable Core16550 interrupts.
+ * They are used to build the value of the irq_mask parameter for the
+ * UART_16550_enable_irq() and UART_16550_disable_irq() functions. A bitwise
+ * OR of these constants is used to enable or disable multiple interrupts.
+ */
+#define UART_16550_RBF_IRQ ( (uint8_t) 0x01 )
+#define UART_16550_TBE_IRQ ( (uint8_t) 0x02 )
+#define UART_16550_LS_IRQ ( (uint8_t) 0x04 )
+#define UART_16550_MS_IRQ ( (uint8_t) 0x08 )
+
+/***************************************************************************//**
+ * Data Width
+ * The following defines are used to build the value of the UART_16550_init()
+ * function line_config parameter.
+ */
+#define UART_16550_DATA_5_BITS ( (uint8_t) 0x00 )
+#define UART_16550_DATA_6_BITS ( (uint8_t) 0x01 )
+#define UART_16550_DATA_7_BITS ( (uint8_t) 0x02 )
+#define UART_16550_DATA_8_BITS ( (uint8_t) 0x03 )
+
+/***************************************************************************//**
+ * Parity Control
+ * The following defines are used to build the value of the UART_16550_init()
+ * function line_config parameter.
+ */
+#define UART_16550_NO_PARITY ( (uint8_t) 0x00 )
+#define UART_16550_ODD_PARITY ( (uint8_t) 0x08 )
+#define UART_16550_EVEN_PARITY ( (uint8_t) 0x18 )
+#define UART_16550_STICK_PARITY_1 ( (uint8_t) 0x28 )
+#define UART_16550_STICK_PARITY_0 ( (uint8_t) 0x38 )
+
+/***************************************************************************//**
+ * Number of Stop Bits
+ * The following defines are used to build the value of the UART_16550_init()
+ * function line_config parameter.
+ */
+#define UART_16550_ONE_STOP_BIT ( (uint8_t) 0x00 )
+/*only when data bits is 5*/
+#define UART_16550_ONEHALF_STOP_BIT ( (uint8_t) 0x04 )
+/*only when data bits is not 5*/
+#define UART_16550_TWO_STOP_BITS ( (uint8_t) 0x04 )
+
+/***************************************************************************//**
+ 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
+ UART_16550_set_rx_handler() function’s trigger_level parameter.
+ */
+typedef enum {
+ UART_16550_FIFO_SINGLE_BYTE = 0,
+ UART_16550_FIFO_FOUR_BYTES = 1,
+ UART_16550_FIFO_EIGHT_BYTES = 2,
+ UART_16550_FIFO_FOURTEEN_BYTES = 3,
+ UART_16550_FIFO_INVALID_TRIG_LEVEL
+} uart_16550_rx_trig_level_t;
+
+/***************************************************************************//**
+ This enumeration specifies the Loopback configuration of the UART. It provides
+ the allowed values for the UART_16550_set_loopback() function’s loopback
+ parameter.
+ */
+typedef enum {
+ UART_16550_LOOPBACK_OFF = 0,
+ UART_16550_LOOPBACK_ON = 1,
+ UART_16550_INVALID_LOOPBACK
+} uart_16550_loopback_t;
+
+/***************************************************************************//**
+ This is type definition for Core16550 instance. You need to create and
+ maintain a record of this type. This holds all data regarding the Core16550
+ instance.
+ */
+typedef struct uart_16550_instance uart_16550_instance_t;
+
+/***************************************************************************//**
+ This typedef specifies the function prototype for Core16550 interrupt handlers.
+ All interrupt handlers registered with the Core16550 driver must be of this
+ type. The interrupt handlers are registered with the driver through the
+ UART_16550_set_rx_handler(), UART_16550_set_tx_handler(),
+ UART_16550_set_rxstatus_handler(), and UART_16550_set_modemstatus_handler()
+ functions.
+
+ The this_uart parameter is a pointer to a uart_16550_instance_t structure that
+ holds all data regarding this instance of the Core16550.
+ */
+typedef void (*uart_16550_irq_handler_t)(uart_16550_instance_t * this_uart);
+
+/***************************************************************************//**
+ uart_16550_instance.
+ This structure is used to identify the various Core16550 hardware instances
+ in your system. Your application software should declare one instance of this
+ structure for each instance of Core16550 in your system. The function
+ UART_16550_init() initializes this structure. A pointer to an initialized
+ instance of the structure should be passed as the first parameter to the
+ Core16550 driver functions, to identify which Core16550 hardware instance
+ should perform the requested operation.
+ */
+struct uart_16550_instance{
+ /* Core16550 instance base address: */
+ addr_t base_address;
+ /* Accumulated status: */
+ uint8_t status;
+
+ /* transmit related info: */
+ const uint8_t* tx_buffer;
+ uint32_t tx_buff_size;
+ uint32_t tx_idx;
+
+ /* line status (OE, PE, FE & BI) interrupt handler:*/
+ uart_16550_irq_handler_t linests_handler;
+ /* receive interrupt handler:*/
+ uart_16550_irq_handler_t rx_handler;
+ /* transmitter holding register interrupt handler:*/
+ uart_16550_irq_handler_t tx_handler;
+ /* modem status interrupt handler:*/
+ uart_16550_irq_handler_t modemsts_handler;
+};
+
+/***************************************************************************//**
+ * The UART_16550_init() function initializes the driver’s data structures and
+ * the Core16550 hardware with the configuration passed as parameters.. The
+ * configuration parameters are the baud_value used to generate the baud rate,
+ * and the line_config used to specify the line configuration (bit length,
+ * stop bits and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550. This pointer
+ * is used to identify the target Core16550 hardware
+ * instance in subsequent calls to the Core16550 driver
+ * functions.
+ * @param base_addr The base_address parameter is the base address in the
+ * processor's memory map for the registers of the
+ * Core16550 instance being initialized.
+ * @param baud_value The baud_value parameter is used to select the baud rate
+ * for the UART. The baud value is calculated from the
+ * frequency of the system clock in Hertz and the desired
+ * baud rate using the following equation:
+ *
+ * baud_value = (clock /(baud_rate * 16))
+ *
+ * The baud_value parameter must be a value in the range 0
+ * to 65535 (or 0x0000 to 0xFFFF).
+ * @param line_config This 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:
+ * • Data lengths:
+ * UART_16550_DATA_5_BITS
+ * UART_16550_DATA_6_BITS
+ * UART_16550_DATA_7_BITS
+ * UART_16550_DATA_8_BITS
+ * • Parity types:
+ * UART_16550_NO_PARITY
+ * UART_16550_EVEN_PARITY
+ * UART_16550_ODD_PARITY
+ * UART_16550_STICK_PARITY_0
+ * UART_16550_STICK_PARITY_1
+ * • Number of stop bits:
+ * UART_16550_ONE_STOP_BIT
+ * UART_16550_ONEHALF_STOP_BIT
+ * UART_16550_TWO_STOP_BITS
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * #define UART_16550_BASE_ADDR 0x2A000000
+ * #define BAUD_VALUE_57600 26
+ *
+ * uart_16550_instance_t g_uart;
+ *
+ * UART_16550_init( &g_uart, UART_16550_BASE_ADDR, BAUD_VALUE_57600,
+ * (UART_16550_DATA_8_BITS |
+ * UART_16550_EVEN_PARITY |
+ * UART_16550_ONE_STOP_BIT) );
+ * @endcode
+ */
+void
+UART_16550_init
+(
+ uart_16550_instance_t* this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ * The UART_16550_polled_tx() function is used to transmit data. It transfers
+ * the contents of the transmitter data buffer, passed as a function parameter,
+ * into the UART's hardware transmitter FIFO. It returns when the full content
+ * of the transmitter data buffer has been transferred to the UART's transmitter
+ * FIFO. 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 UART_16550_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 a
+ * uart_16550_instance_t structure that holds all
+ * data regarding this instance of the Core16550.
+ * @param pbuff The pbuff parameter is a pointer to a buffer containing
+ * the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size, in bytes, of the
+ * data to be transmitted.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\n\r\n\r\n\rUART_16550_polled_tx() test message 1"};
+ * UART_16550_polled_tx(&g_uart,(const uint8_t *)testmsg1,sizeof(testmsg1));
+ * @endcode
+ */
+void
+UART_16550_polled_tx
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+);
+/***************************************************************************//**
+ * The UART_16550_polled_tx_string() function 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 UART_16550_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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @param p_sz_string The p_sz_string parameter is a pointer to a buffer
+ * containing the NULL ('\0') terminated string to be
+ * transmitted.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\r\n\r\nUART_16550_polled_tx_string() test message 1\0"};
+ * UART_16550_polled_tx_string(&g_uart,(const uint8_t *)testmsg1);
+ * @endcode
+ */
+void
+UART_16550_polled_tx_string
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * p_sz_string
+);
+
+/***************************************************************************//**
+ * The UART_16550_irq_tx() function is used to initiate an interrupt driven
+ * transmit. It returns immediately after making a note of the transmit buffer
+ * location and enabling the transmitter holding register empty (THRE) interrupt
+ * at the Core16550 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 UART_16550_tx_complete().The actual transmission over the serial
+ * connection is still in progress until calls to the UART_16550_tx_complete()
+ * function indicate transmit completion.
+ *
+ * Note: It is your responsibility to call UART_16550_isr(), the driver’s
+ * top level interrupt handler function, from the system level (CoreInterrupt
+ * and NVIC level) interrupt handler assigned to the interrupt triggered by the
+ * Core16550 INTR signal. You must do this before using the UART_16550_irq_tx()
+ * function.
+ *
+ * Note: It is also your responsibility to enable the system level
+ * (CoreInterrupt and NVIC level) interrupt connected to the Core16550 INTR
+ * interrupt signal.
+ *
+ * Note: The UART_16550_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 UART_16550_set_tx_handler() function.
+ *
+ * Note: The UART_16550_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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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
+ * uint8_t tx_buff[10] = "abcdefghi";
+ *
+ * UART_16550_irq_tx( &g_uart, tx_buff, sizeof(tx_buff));
+ * while ( 0 == UART_16550_tx_complete( &g_uart ) )
+ * { ; }
+ * @endcode
+ */
+void
+UART_16550_irq_tx
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * pbuff,
+ uint32_t tx_size
+);
+
+/***************************************************************************//**
+ * The UART_16550_tx_complete() function is used to find out if the interrupt
+ * driven transmit previously initiated through a call to UART_16550_irq_tx()
+ * is complete. This function is typically used to find out when it is safe
+ * to reuse or release the memory buffer holding the 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 UART_16550_tx_complete() function indicate
+ * transmit completion.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @return This function returns a non-zero value if transmit has
+ * completed, otherwise it returns zero.
+ * Example:
+ * See the UART_16550_irq_tx() function for an example that uses the
+ * UART_16550_tx_complete() function.
+ */
+int8_t
+UART_16550_tx_complete
+(
+ uart_16550_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ * The UART_16550_get_rx() function reads the content of the Core16550
+ * 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 UART_16550_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 UART_16550_get_rx() function reads and accumulates the receiver
+ * status of the Core16550 instance before reading each byte from the receiver's
+ * data register/FIFO. This allows the driver to maintain a sticky record of any
+ * receiver errors that occur as the UART receives each data byte; receiver errors
+ * would otherwise be lost after each read from the receiver's data register. A call
+ * to the UART_16550_get_rx_status() function returns any receiver errors accumulated
+ * during the execution of the UART_16550_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
+ * UART_16550_get_rx_status() function.
+ * The UART_16550_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 UART_16550_get_rx()
+ * function as part of the receive handler function that you register with the
+ * Core16550 driver through a call to UART_16550_set_rx_handler().
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @param rx_buff The rx_buff parameter is a pointer to a memory buffer
+ * where the received data is copied.
+ * @param buff_size The buff_size parameter is the size of the receive
+ * buffer in bytes.
+ * @return This function returns the number of bytes copied into
+ * the receive buffer.
+ * Example:
+ * @code
+ * #define MAX_RX_DATA_SIZE 256
+ *
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t rx_size = 0;
+ *
+ * rx_size = UART_16550_get_rx( &g_uart, rx_data, sizeof(rx_data) );
+ * @endcode
+ */
+size_t
+UART_16550_get_rx
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t * rx_buff,
+ size_t buff_size
+);
+
+/***************************************************************************//**
+ * The UART_16550_isr() function is the top level interrupt handler function for
+ * the Core16550 driver. You must call UART_16550_isr() from the system level
+ * (CoreInterrupt and NVIC level) interrupt handler assigned to the interrupt
+ * triggered by the Core16550 INTR signal. Your system level interrupt handler
+ * must also clear the system level interrupt triggered by the Core16550 INTR
+ * signal before returning, to prevent a re-assertion of the same interrupt.
+ *
+ * Note: This function supports all types of interrupt triggered by Core16550.
+ * It is not a complete interrupt handler by itself; rather, it is a top level
+ * wrapper that abstracts Core16550 interrupt handling by calling lower level
+ * handler functions specific to each type of Core16550 interrupt. You must
+ * create the lower level handler functions to suit your application and
+ * register them with the driver through calls to the UART_16550_set_rx_handler(),
+ * UART_16550_set_tx_handler(), UART_16550_set_rxstatus_handler() and
+ * UART_16550_set_modemstatus_handler() functions.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ *
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * void CIC_irq1_handler(void)
+ * {
+ * UART_16550_isr( &g_uart );
+ * }
+ * @endcode
+ */
+void
+UART_16550_isr
+(
+ uart_16550_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ * The UART_16550_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. The UART_16550_set_rx_handler() function also enables the
+ * RDA interrupt at the Core16550 level. You must create and register the receive
+ * handler function to suit your application and it must include a call to the
+ * UART_16550_get_rx() function to actually read the received data.
+ *
+ * Note: The driver’s top level interrupt handler function UART_16550_isr()
+ * will call your receive handler function in response to an RDA interrupt from
+ * the Core16550.
+ *
+ * Note: You can disable the RDA interrupt once the data is received by calling
+ * the UART_16550_disable_irq() function. This is your choice and is dependent
+ * upon your application.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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 uart_16550_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 "core_16550.h"
+ *
+ * #define RX_BUFF_SIZE 64
+ * #define UART_57600_BAUD 26
+ *
+ * uint8_t g_rx_buff[RX_BUFF_SIZE];
+ * uart_16550_instance_t g_uart;
+ * void uart_rx_handler( uart_16550_instance_t * this_uart )
+ * {
+ * UART_16550_get_rx( this_uart, g_rx_buff, RX_BUFF_SIZE );
+ * }
+ *
+ * int main(void)
+ * {
+ * UART_16550_init( &g_uart, UART_57600_BAUD,
+ * ( UART_16550_DATA_8_BITS | UART_16550_NO_PARITY ) );
+ * UART_16550_set_rx_handler( &g_uart, uart_rx_handler,
+ * UART_16550_FIFO_SINGLE_BYTE);
+ * while ( 1 )
+ * {
+ * ;
+ * }
+ * return(0);
+ * }
+ * @endcode
+ */
+void
+UART_16550_set_rx_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler,
+ uart_16550_rx_trig_level_t trigger_level
+);
+
+/***************************************************************************//**
+ * The UART_16550_set_loopback() function is used to locally loopback the Tx
+ * and Rx lines of a Core16550 UART.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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:
+ * • UART_16550_LOOPBACK_ON
+ * • UART_16550_LOOPBACK_OFF
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * #include "core_16550.h"
+ *
+ * #define UART_57600_BAUD 26
+ * #define DATA_SIZE 4
+ *
+ * uart_16550_instance_t g_uart;
+ *
+ * int main(void)
+ * {
+ * uint8_t txbuf[DATA_SIZE] = "abc";
+ * uint8_t rxbuf[DATA_SIZE];
+ * UART_16550_init( &g_uart, UART_57600_BAUD,
+ * ( UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |
+ * UART_16550_ONE_STOP_BIT) );
+ * UART_16550_set_loopback( &g_uart, UART_16550_LOOPBACK_ON );
+ *
+ * while(1)
+ * {
+ * UART_16550_polled_tx( &g_uart, txbuf, DATA_SIZE);
+ * delay(100);
+ * UART_16550_get_rx( &g_uart, rxbuf, DATA_SIZE);
+ * }
+ * }
+ * @endcode
+ */
+void
+UART_16550_set_loopback
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_loopback_t loopback
+);
+
+/***************************************************************************//**
+ * The UART_16550_get_rx_status() function returns the receiver error status of
+ * the Core16550 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 UART_16550_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
+ * UART_16550_get_rx_status(), as an 8-bit encoded value.
+ *
+ * Note: The UART_16550_get_rx() function reads and accumulates the receiver
+ * status of the Core16550 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 UART_16550_get_rx() function
+ * returns. The UART_16550_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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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:
+ * • UART_16550_OVERRUN_ERROR (bit mask = 0x02)
+ * • UART_16550_PARITY_ERROR (bit mask = 0x04)
+ * • UART_16550_FRAMING_ERROR (bit mask = 0x08)
+ * • UART_16550_BREAK_ERROR (bit mask = 0x10)
+ * • UART_16550_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:
+ * • UART_16550_NO_ERROR (bit mask = 0x00)
+ * Upon unsuccessful execution, this function returns:
+ * • UART_16550_INVALID_PARAM (bit mask = 0xFF)
+ *
+ * Example:
+ * @code
+ * uart_16550_instance_t g_uart;
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t err_status;
+ *
+ * err_status = UART_16550_get_rx_status(&g_uart);
+ * if(UART_16550_NO_ERROR == err_status )
+ * {
+ * rx_size = UART_16550_get_rx( &g_uart, rx_data, MAX_RX_DATA_SIZE );
+ * }
+ * @endcode
+ */
+uint8_t
+UART_16550_get_rx_status
+(
+ uart_16550_instance_t * this_uart
+);
+/***************************************************************************//**
+ * The UART_16550_enable_irq() function enables the Core16550 interrupts
+ * specified by the irq_mask parameter. The irq_mask parameter identifies the
+ * Core16550 interrupts by bit position, as defined in the interrupt enable
+ * register (IER) of Core16550. The Core16550 interrupts and their identifying
+ * irq_mask bit positions are as follows:
+ * • Receive data available interrupt (RDA) (irq_mask bit 0)
+ * • Transmit holding register empty interrupt (THRE) (irq_mask bit 1)
+ * • Receiver line status interrupt (LS) (irq_mask bit 2)
+ * • Modem status interrupt (MS) (irq_mask bit 3)
+ * When an irq_mask bit position is set to 1, this function enables the
+ * corresponding Core16550 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.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @param irq_mask The irq_mask parameter is used to select which of the
+ * Core16550’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:
+ * • UART_16550_RBF_IRQ (bit mask = 0x01)
+ * • UART_16550_TBE_IRQ (bit mask = 0x02)
+ * • UART_16550_LS_IRQ (bit mask = 0x04)
+ * • UART_16550_MS_IRQ (bit mask = 0x08)
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * UART_16550_enable_irq( &g_uart,( UART_16550_RBF_IRQ | UART_16550_TBE_IRQ ) );
+ * @endcode
+ */
+void
+UART_16550_enable_irq
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t irq_mask
+);
+
+/***************************************************************************//**
+ * The UART_16550_disable_irq() function disables the Core16550 interrupts
+ * specified by the irq_mask parameter. The irq_mask parameter identifies the
+ * Core16550 interrupts by bit position, as defined in the interrupt enable
+ * register (IER) of Core16550. The Core16550 interrupts and their identifying
+ * bit positions are as follows:
+ * • Receive data available interrupt (RDA) (irq_mask bit 0)
+ * • Transmit holding register empty interrupt (THRE) (irq_mask bit 1)
+ * • Receiver line status interrupt (LS) (irq_mask bit 2)
+ * • Modem status interrupt (MS) (irq_mask bit 3)
+ * When an irq_mask bit position is set to 1, this function disables the
+ * corresponding Core16550 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.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @param irq_mask The irq_mask parameter is used to select which of the
+ * Core16550’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:
+ * • UART_16550_RBF_IRQ (bit mask = 0x01)
+ * • UART_16550_TBE_IRQ (bit mask = 0x02)
+ * • UART_16550_LS_IRQ (bit mask = 0x04)
+ * • UART_16550_MS_IRQ (bit mask = 0x08)
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * UART_16550_disable_irq( &g_uart, ( UART_16550_RBF_IRQ | UART_16550_TBE_IRQ ) );
+ * @endcode
+ */
+void
+UART_16550_disable_irq
+(
+ uart_16550_instance_t * this_uart,
+ uint8_t irq_mask
+);
+
+/***************************************************************************//**
+ * The UART_16550_get_modem_status() function returns the modem status of the
+ * Core16550 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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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:
+ * • UART_16550_DCTS (bit mask = 0x01)
+ * • UART_16550_DDSR (bit mask = 0x02)
+ * • UART_16550_TERI (bit mask = 0x04)
+ * • UART_16550_DDCD (bit mask = 0x08)
+ * • UART_16550_CTS (bit mask = 0x10)
+ * • UART_16550_DSR (bit mask = 0x20)
+ * • UART_16550_RI (bit mask = 0x40)
+ * • UART_16550_DCD (bit mask = 0x80)
+ * Example:
+ * @code
+ * void uart_modem_status_isr(uart_16550_instance_t * this_uart)
+ * {
+ * uint8_t status;
+ * status = UART_16550_get_modem_status( this_uart );
+ * if( status & UART_16550_DCTS )
+ * {
+ * uart_dcts_handler();
+ * }
+ * if( status & UART_16550_CTS )
+ * {
+ * uart_cts_handler();
+ * }
+ * }
+ * @endcode
+ */
+uint8_t
+UART_16550_get_modem_status
+(
+ uart_16550_instance_t * this_uart
+);
+
+/***************************************************************************//**
+ * The UART_16550_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. The UART_16550_set_rxstatus_handler()
+ * function also enables the RLS interrupt at the Core16550 level. You must
+ * create and register the receiver status handler function to suit your
+ * application.
+ *
+ * Note: The driver’s top level interrupt handler function UART_16550_isr()
+ * will call your receive status handler function in response to an RLS
+ * interrupt from the Core16550.
+ *
+ * Note: You can disable the RLS interrupt when required by calling the
+ * UART_16550_disable_irq() function. This is your choice and is dependent
+ * upon your application.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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 uart_16550_irq_handler_t.
+ * Example:
+ * @code
+ * #include "core_16550.h"
+ *
+ * #define UART_57600_BAUD 26
+ *
+ * uart_16550_instance_t g_uart;
+ *
+ * void uart_rxsts_handler( uart_16550_instance_t * this_uart )
+ * {
+ * uint8_t status;
+ * status = UART_16550_get_rx_status( this_uart );
+ * if( status & UART_16550_OVERUN_ERROR )
+ * {
+ * discard_rx_data();
+ * }
+ * }
+ *
+ * int main(void)
+ * {
+ * UART_16550_init( &g_uart, UART_57600_BAUD,
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |
+ * UART_16550_ONE_STOP_BIT );
+ * UART_16550_set_rxstatus_handler( &g_uart, uart_rxsts_handler );
+ *
+ * while ( 1 )
+ * {
+ * ;
+ * }
+ * return(0);
+ * }
+ * @endcode
+ */
+void
+UART_16550_set_rxstatus_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ * The UART_16550_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. The UART_16550_set_tx_handler()
+ * function also enables the THRE interrupt at the Core16550 level. You must
+ * create and register the transmit handler function to suit your application.
+ * You can use the UART_16550_fill_tx_fifo() function in your transmit handler
+ * function to write data to the transmitter.
+ *
+ * Note: The driver’s top level interrupt handler function UART_16550_isr()
+ * will call your transmit handler function in response to an THRE interrupt
+ * from the Core16550.
+ *
+ * Note: You can disable the THRE interrupt when required by calling the
+ * UART_16550_disable_irq() function. This is your choice and is dependent
+ * upon your application.
+ *
+ * Note: The UART_16550_irq_tx() function does not use the transmit handler
+ * function that you register with the UART_16550_set_tx_handler() function.
+ * It uses its own internal THRE interrupt handler function that overrides any
+ * custom interrupt handler that you register using the
+ * UART_16550_set_tx_handler() function.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @param handler The handler parameter is a pointer to a transmitter
+ * interrupt handler function provided by your application,
+ * which will be called as a result of a UART THRE interrupt.
+ * This handler is of uart_16550_irq_handler_t type.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * #include "core_16550.h"
+ *
+ * #define UART_57600_BAUD 26
+ *
+ * uart_16550_instance_t g_uart;
+ *
+ * uint8_t * g_tx_buffer;
+ * size_t g_tx_size = 0;
+ *
+ * void uart_tx_handler( uart_16550_instance_t * this_uart )
+ * {
+ * size_t size_in_fifo;
+ *
+ * size_in_fifo = UART_16550_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;
+ * UART_16550_disable_irq( this_uart, UART_16550_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";
+ *
+ * UART_16550_init( &g_uart, UART_57600_BAUD,
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |
+ * UART_16550_ONE_STOP_BIT );
+ *
+ * g_tx_buffer = message;
+ * g_tx_size = sizeof(message);
+ *
+ * UART_16550_set_tx_handler( &g_uart, uart_tx_handler);
+ *
+ * while ( 1 )
+ * {
+ * ;
+ * }
+ * return(0);
+ * }
+ *
+ * @endcode
+ */
+void
+UART_16550_set_tx_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ * The UART_16550_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. The UART_16550_set_modemstatus_handler()
+ * function also enables the MS interrupt at the Core16550 level. You must
+ * create and register the modem status handler function to suit your
+ * application.
+ *
+ * Note: The driver’s top level interrupt handler function UART_16550_isr()
+ * will call your receive status handler function in response to an MS interrupt
+ * from the Core16550.
+ *
+ * Note: You can disable the MS interrupt when required by calling the
+ * UART_16550_disable_irq() function. This is your choice and is dependent
+ * upon your application.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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
+ * uart_16550_irq_handler_t.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * #include "core_16550.h"
+ *
+ * #define UART_57600_BAUD 26
+ *
+ * uart_16550_instance_t g_uart;
+ *
+ * void uart_modem_handler( uart_16550_instance_t * this_uart )
+ * {
+ * uint8_t status;
+ * status = UART_16550_get_modem_status( this_uart );
+ * if( status & UART_16550_CTS )
+ * {
+ * uart_cts_handler();
+ * }
+ * }
+ *
+ * int main(void)
+ * {
+ * UART_16550_init( &g_uart, UART_57600_BAUD,
+ * UART_16550_DATA_8_BITS | UART_16550_NO_PARITY |
+ UART_16550_ONE_STOP_BIT);
+ * UART_16550_set_modemstatus_handler( &g_uart, uart_modem_handler);
+ *
+ * while ( 1 )
+ * {
+ * ;
+ * }
+ * return(0);
+ * }
+ * @endcode
+ */
+void
+UART_16550_set_modemstatus_handler
+(
+ uart_16550_instance_t * this_uart,
+ uart_16550_irq_handler_t handler
+);
+
+/***************************************************************************//**
+ * The UART_16550_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 UART_16550_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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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 = UART_16550_fill_tx_fifo( &g_uart, pbuff, tx_size );
+ * }
+ * @endcode
+ */
+size_t
+UART_16550_fill_tx_fifo
+(
+ uart_16550_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ * The UART_16550_get_tx_status() function returns the transmitter status of
+ * the Core16550 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 a
+ * uart_16550_instance_t structure that holds all data
+ * regarding this instance of the Core16550.
+ * @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
+ * bitmasks, a non-zero result indicates that the
+ * corresponding transmitter status bit is set:
+ * • UART_16550_THRE (bit mask = 0x20)
+ * • UART_16550_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.
+ * • UART_16550_TX_BUSY (bit mask = 0x00)
+ * Example:
+ * @code
+ * uint8_t tx_buff[10] = "abcdefghi";
+ *
+ * UART_16550_polled_tx( &g_uart, tx_buff, sizeof(tx_buff));
+ *
+ * while ( ! (UART_16550_TEMT & UART_16550_get_tx_status( &g_uart ) ) )
+ * {
+ * ;
+ * }
+ * @endcode
+ */
+uint8_t
+UART_16550_get_tx_status
+(
+ uart_16550_instance_t * this_uart
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_16550_H */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.c
new file mode 100644
index 000000000..e5dbd7edf
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.c
@@ -0,0 +1,461 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreGPIO bare metal driver implementation.
+ *
+ * SVN $Revision: 7964 $
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $
+ */
+#include "core_gpio.h"
+#include "hal.h"
+#include "hal_assert.h"
+#include "coregpio_regs.h"
+
+/*-------------------------------------------------------------------------*//**
+ *
+ */
+#define GPIO_INT_ENABLE_MASK (uint32_t)0x00000008UL
+#define OUTPUT_BUFFER_ENABLE_MASK 0x00000004UL
+
+
+#define NB_OF_GPIO 32
+
+#define CLEAR_ALL_IRQ32 (uint32_t)0xFFFFFFFF
+#define CLEAR_ALL_IRQ16 (uint16_t)0xFFFF
+#define CLEAR_ALL_IRQ8 (uint8_t)0xFF
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_init()
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_init
+(
+ gpio_instance_t * this_gpio,
+ addr_t base_addr,
+ gpio_apb_width_t bus_width
+)
+{
+ uint8_t i = 0;
+ addr_t cfg_reg_addr = base_addr;
+
+ this_gpio->base_addr = base_addr;
+ this_gpio->apb_bus_width = bus_width;
+
+ /* Clear configuration. */
+ for( i = 0, cfg_reg_addr = base_addr; i < NB_OF_GPIO; ++i )
+ {
+ HW_set_8bit_reg( cfg_reg_addr, 0 );
+ cfg_reg_addr += 4;
+ }
+ /* Clear any pending interrupts */
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, CLEAR_ALL_IRQ32 );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, (uint16_t)CLEAR_ALL_IRQ16 );
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, (uint16_t)CLEAR_ALL_IRQ16 );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, (uint8_t)CLEAR_ALL_IRQ8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, (uint8_t)CLEAR_ALL_IRQ8 );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_config
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_config
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint32_t config
+)
+{
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+ cfg_reg_addr += (port_id * 4);
+ HW_set_32bit_reg( cfg_reg_addr, config );
+
+ /*
+ * Verify that the configuration was correctly written. Failure to read
+ * back the expected value may indicate that the GPIO port was configured
+ * as part of the hardware flow and cannot be modified through software.
+ * It may also indicate that the base address passed as parameter to
+ * GPIO_init() was incorrect.
+ */
+ HAL_ASSERT( HW_get_32bit_reg( cfg_reg_addr ) == config );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_set_outputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_set_outputs
+(
+ gpio_instance_t * this_gpio,
+ uint32_t value
+)
+{
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, value );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint16_t)value );
+ HAL_set_16bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint16_t)(value >> 16) );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT0, (uint8_t)value );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT1, (uint8_t)(value >> 8) );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT2, (uint8_t)(value >> 16) );
+ HAL_set_8bit_reg( this_gpio->base_addr, GPIO_OUT3, (uint8_t)(value >> 24) );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( GPIO_get_outputs( this_gpio ) == value );
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_get_inputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+uint32_t GPIO_get_inputs
+(
+ gpio_instance_t * this_gpio
+)
+{
+ uint32_t gpio_in = 0;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ gpio_in = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_IN );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ gpio_in |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN0 );
+ gpio_in |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 16);
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ gpio_in |= HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN0 );
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN1 ) << 8);
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN2 ) << 16);
+ gpio_in |= (HAL_get_8bit_reg( this_gpio->base_addr, GPIO_IN3 ) << 24);
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ return gpio_in;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_get_outputs
+ * See "core_gpio.h" for details of how to use this function.
+ */
+uint32_t GPIO_get_outputs
+(
+ gpio_instance_t * this_gpio
+)
+{
+ uint32_t gpio_out = 0;
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ gpio_out = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 16);
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ gpio_out |= HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT0 );
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT1 ) << 8);
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT2 ) << 16);
+ gpio_out |= (HAL_get_16bit_reg( this_gpio->base_addr, GPIO_OUT3 ) << 24);
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+
+ return gpio_out;
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_set_output
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_set_output
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint8_t value
+)
+{
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ {
+ uint32_t outputs_state;
+
+ outputs_state = HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << port_id);
+ }
+ else
+ {
+ outputs_state |= 1 << port_id;
+ }
+ HAL_set_32bit_reg( this_gpio->base_addr, GPIO_OUT, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HAL_get_32bit_reg( this_gpio->base_addr, GPIO_OUT ) == outputs_state );
+ }
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ {
+ uint16_t outputs_state;
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 4) * 4);
+
+ outputs_state = HW_get_16bit_reg( gpio_out_reg_addr );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << (port_id & 0x0F));
+ }
+ else
+ {
+ outputs_state |= 1 << (port_id & 0x0F);
+ }
+ HW_set_16bit_reg( gpio_out_reg_addr, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HW_get_16bit_reg( gpio_out_reg_addr ) == outputs_state );
+ }
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ {
+ uint8_t outputs_state;
+ uint32_t gpio_out_reg_addr = this_gpio->base_addr + GPIO_OUT_REG_OFFSET + ((port_id >> 3) * 4);
+
+ outputs_state = HW_get_8bit_reg( gpio_out_reg_addr );
+ if ( 0 == value )
+ {
+ outputs_state &= ~(1 << (port_id & 0x07));
+ }
+ else
+ {
+ outputs_state |= 1 << (port_id & 0x07);
+ }
+ HW_set_8bit_reg( gpio_out_reg_addr, outputs_state );
+
+ /*
+ * Verify that the output register was correctly written. Failure to read back
+ * the expected value may indicate that some of the GPIOs may not exist due to
+ * the number of GPIOs selected in the CoreGPIO hardware flow configuration.
+ * It may also indicate that the base address or APB bus width passed as
+ * parameter to the GPIO_init() function do not match the hardware design.
+ */
+ HAL_ASSERT( HW_get_8bit_reg( gpio_out_reg_addr ) == outputs_state );
+ }
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_drive_inout
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_drive_inout
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ gpio_inout_state_t inout_state
+)
+{
+ uint32_t config;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ switch( inout_state )
+ {
+ case GPIO_DRIVE_HIGH:
+ /* Set output high */
+ GPIO_set_output( this_gpio, port_id, 1 );
+
+ /* Enable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ case GPIO_DRIVE_LOW:
+ /* Set output low */
+ GPIO_set_output( this_gpio, port_id, 0 );
+
+ /* Enable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config |= OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ case GPIO_HIGH_Z:
+ /* Disable output buffer */
+ cfg_reg_addr = this_gpio->base_addr + (port_id * 4);
+ config = HW_get_8bit_reg( cfg_reg_addr );
+ config &= ~OUTPUT_BUFFER_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, config );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_enable_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_enable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ cfg_reg_addr += (port_id * 4);
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );
+ cfg_value |= GPIO_INT_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_disable_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_disable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t cfg_value;
+ uint32_t cfg_reg_addr = this_gpio->base_addr;
+
+ HAL_ASSERT( port_id < NB_OF_GPIO );
+
+ if ( port_id < NB_OF_GPIO )
+ {
+ cfg_reg_addr += (port_id * 4);
+ cfg_value = HW_get_8bit_reg( cfg_reg_addr );
+ cfg_value &= ~GPIO_INT_ENABLE_MASK;
+ HW_set_8bit_reg( cfg_reg_addr, cfg_value );
+ }
+}
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO_clear_irq
+ * See "core_gpio.h" for details of how to use this function.
+ */
+void GPIO_clear_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+)
+{
+ uint32_t irq_clr_value = ((uint32_t)1) << ((uint32_t)port_id);
+
+ switch( this_gpio->apb_bus_width )
+ {
+ case GPIO_APB_32_BITS_BUS:
+ HAL_set_32bit_reg( this_gpio->base_addr, IRQ, irq_clr_value );
+ break;
+
+ case GPIO_APB_16_BITS_BUS:
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_16bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 16 );
+ break;
+
+ case GPIO_APB_8_BITS_BUS:
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ0, irq_clr_value );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ1, irq_clr_value >> 8 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ2, irq_clr_value >> 16 );
+ HAL_set_8bit_reg( this_gpio->base_addr, IRQ3, irq_clr_value >> 24 );
+ break;
+
+ default:
+ HAL_ASSERT(0);
+ break;
+ }
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.h
new file mode 100644
index 000000000..68799be27
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/core_gpio.h
@@ -0,0 +1,552 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreGPIO bare metal driver public API.
+ *
+ * SVN $Revision: 7964 $
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $
+ */
+
+/*=========================================================================*//**
+ @mainpage CoreGPIO Bare Metal Driver.
+
+ @section intro_sec Introduction
+ The CoreGPIO hardware IP includes up to 32 general purpose input output GPIOs.
+ This driver provides a set of functions for controlling the GPIOs as part of a
+ bare metal system where no operating system is available. These drivers
+ can be adapted for use as part of an operating system but the implementation
+ of the adaptation layer between this driver and the operating system's driver
+ model is outside the scope of this driver.
+
+ @section driver_configuration Driver Configuration
+ The CoreGPIO individual IOs can be configured either in the hardware flow or
+ as part of the software application through calls to the GPIO_config() function.
+ GPIOs configured as as part of the hardware is fixed and cannot be modified
+ using a call to the GPI_config() function.
+
+ @section theory_op Theory of Operation
+ The CoreGPIO driver uses the Actel Hardware Abstraction Layer (HAL) to access
+ hardware registers. You must ensure that the Actel HAL is included as part of
+ your software project. The Actel HAL is available through the Actel Firmware
+ Catalog.
+
+ The CoreGPIO driver functions are logically grouped into the following groups:
+ - Initiliazation
+ - Configuration
+ - Reading and writing GPIO state
+ - Interrupt control
+
+ The CoreGPIO driver is initialized through a call to the GPIO_init() function.
+ The GPIO_init() function must be called before any other GPIO driver functions
+ can be called.
+
+ Each GPIO port is individually configured through a call to the
+ GPIO_config() function. Configuration includes deciding if a GPIO port
+ will be used as input, output or both. GPIO ports configured as inputs can be
+ further configured to generate interrupts based on the input's state.
+ Interrupts can be level or edge sensitive.
+ Please note that a CoreGPIO hardware instance can be generated, as part of the
+ hardware flow, with a fixed configuration for some or all of its IOs. Attempting
+ to modify the configuration of such a hardware configured IO using the
+ GPIO_config() function has no effect.
+
+ The state of the GPIO ports can be read and written using the following
+ functions:
+ - GPIO_get_inputs()
+ - GPIO_get_outputs()
+ - GPIO_set_outputs()
+ - GPIO_drive_inout()
+
+ Interrupts generated by GPIO ports configured as inputs are controlled using
+ the following functions:
+ - GPIO_enable_irq()
+ - GPIO_disable_irq()
+ - GPIO_clear_irq()
+
+ *//*=========================================================================*/
+#ifndef CORE_GPIO_H_
+#define CORE_GPIO_H_
+
+#include
+#include "cpu_types.h"
+
+/*-------------------------------------------------------------------------*//**
+ The gpio_id_t enumeration is used to identify GPIOs as part of the
+ parameter to functions:
+ - GPIO_config(),
+ - GPIO_drive_inout(),
+ - GPIO_enable_int(),
+ - GPIO_disable_int(),
+ - GPIO_clear_int()
+ */
+typedef enum __gpio_id_t
+{
+ GPIO_0 = 0,
+ GPIO_1 = 1,
+ GPIO_2 = 2,
+ GPIO_3 = 3,
+ GPIO_4 = 4,
+ GPIO_5 = 5,
+ GPIO_6 = 6,
+ GPIO_7 = 7,
+ GPIO_8 = 8,
+ GPIO_9 = 9,
+ GPIO_10 = 10,
+ GPIO_11 = 11,
+ GPIO_12 = 12,
+ GPIO_13 = 13,
+ GPIO_14 = 14,
+ GPIO_15 = 15,
+ GPIO_16 = 16,
+ GPIO_17 = 17,
+ GPIO_18 = 18,
+ GPIO_19 = 19,
+ GPIO_20 = 20,
+ GPIO_21 = 21,
+ GPIO_22 = 22,
+ GPIO_23 = 23,
+ GPIO_24 = 24,
+ GPIO_25 = 25,
+ GPIO_26 = 26,
+ GPIO_27 = 27,
+ GPIO_28 = 28,
+ GPIO_29 = 29,
+ GPIO_30 = 30,
+ GPIO_31 = 31
+} gpio_id_t;
+
+typedef enum __gpio_apb_width_t
+{
+ GPIO_APB_8_BITS_BUS = 0,
+ GPIO_APB_16_BITS_BUS = 1,
+ GPIO_APB_32_BITS_BUS = 2,
+ GPIO_APB_UNKNOWN_BUS_WIDTH = 3
+} gpio_apb_width_t;
+
+/*-------------------------------------------------------------------------*//**
+ */
+typedef struct __gpio_instance_t
+{
+ addr_t base_addr;
+ gpio_apb_width_t apb_bus_width;
+} gpio_instance_t;
+
+/*-------------------------------------------------------------------------*//**
+ GPIO ports definitions used to identify GPIOs as part of the parameter to
+ function GPIO_set_outputs().
+ These definitions can also be used to identity GPIO through logical
+ operations on the return value of function GPIO_get_inputs().
+ */
+#define GPIO_0_MASK 0x00000001UL
+#define GPIO_1_MASK 0x00000002UL
+#define GPIO_2_MASK 0x00000004UL
+#define GPIO_3_MASK 0x00000008UL
+#define GPIO_4_MASK 0x00000010UL
+#define GPIO_5_MASK 0x00000020UL
+#define GPIO_6_MASK 0x00000040UL
+#define GPIO_7_MASK 0x00000080UL
+#define GPIO_8_MASK 0x00000100UL
+#define GPIO_9_MASK 0x00000200UL
+#define GPIO_10_MASK 0x00000400UL
+#define GPIO_11_MASK 0x00000800UL
+#define GPIO_12_MASK 0x00001000UL
+#define GPIO_13_MASK 0x00002000UL
+#define GPIO_14_MASK 0x00004000UL
+#define GPIO_15_MASK 0x00008000UL
+#define GPIO_16_MASK 0x00010000UL
+#define GPIO_17_MASK 0x00020000UL
+#define GPIO_18_MASK 0x00040000UL
+#define GPIO_19_MASK 0x00080000UL
+#define GPIO_20_MASK 0x00100000UL
+#define GPIO_21_MASK 0x00200000UL
+#define GPIO_22_MASK 0x00400000UL
+#define GPIO_23_MASK 0x00800000UL
+#define GPIO_24_MASK 0x01000000UL
+#define GPIO_25_MASK 0x02000000UL
+#define GPIO_26_MASK 0x04000000UL
+#define GPIO_27_MASK 0x08000000UL
+#define GPIO_28_MASK 0x10000000UL
+#define GPIO_29_MASK 0x20000000UL
+#define GPIO_30_MASK 0x40000000UL
+#define GPIO_31_MASK 0x80000000UL
+
+/*-------------------------------------------------------------------------*//**
+ * GPIO modes
+ */
+#define GPIO_INPUT_MODE 0x0000000002UL
+#define GPIO_OUTPUT_MODE 0x0000000005UL
+#define GPIO_INOUT_MODE 0x0000000003UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible GPIO inputs interrupt configurations.
+ */
+#define GPIO_IRQ_LEVEL_HIGH 0x0000000000UL
+#define GPIO_IRQ_LEVEL_LOW 0x0000000020UL
+#define GPIO_IRQ_EDGE_POSITIVE 0x0000000040UL
+#define GPIO_IRQ_EDGE_NEGATIVE 0x0000000060UL
+#define GPIO_IRQ_EDGE_BOTH 0x0000000080UL
+
+/*-------------------------------------------------------------------------*//**
+ * Possible states for GPIO configured as INOUT.
+ */
+typedef enum gpio_inout_state
+{
+ GPIO_DRIVE_LOW = 0,
+ GPIO_DRIVE_HIGH,
+ GPIO_HIGH_Z
+} gpio_inout_state_t;
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_init() function initialises a CoreGPIO hardware instance and the data
+ structure associated with the CoreGPIO hardware instance.
+ Please note that a CoreGPIO hardware instance can be generated with a fixed
+ configuration for some or all of its IOs as part of the hardware flow. Attempting
+ to modify the configuration of such a hardware configured IO using the
+ GPIO_config() function has no effect.
+
+ @param this_gpio
+ Pointer to the gpio_instance_t data structure instance holding all data
+ regarding the CoreGPIO hardware instance being initialized. A pointer to the
+ same data structure will be used in subsequent calls to the CoreGPIO driver
+ functions in order to identify the CoreGPIO instance that should perform the
+ operation implemented by the called driver function.
+
+ @param base_addr
+ The base_addr parameter is the base address in the processor's memory map for
+ the registers of the GPIO instance being initialized.
+
+ @param bus_width
+ The bus_width parameter informs the driver of the APB bus width selected during
+ the hardware flow configuration of the CoreGPIO hardware instance. It indicates
+ to the driver whether the CoreGPIO hardware registers will be visible as 8, 16
+ or 32 bits registers. Allowed value are:
+ - GPIO_APB_8_BITS_BUS
+ - GPIO_APB_16_BITS_BUS
+ - GPIO_APB_32_BITS_BUS
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREGPIO_BASE_ADDR 0xC2000000
+
+ gpio_instance_t g_gpio;
+
+ void system_init( void )
+ {
+ GPIO_init( &g_gpio, COREGPIO_BASE_ADDR, GPIO_APB_32_BITS_BUS );
+ }
+ @endcode
+ */
+void GPIO_init
+(
+ gpio_instance_t * this_gpio,
+ addr_t base_addr,
+ gpio_apb_width_t bus_width
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_config() function is used to configure an individual GPIO port.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO port to be configured.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @param config
+ The config parameter specifies the configuration to be applied to the GPIO
+ port identified by the first parameter. It is a logical OR of GPIO mode and
+ the interrupt mode. The interrupt mode is only relevant if the GPIO is
+ configured as input.
+ Possible modes are:
+ - GPIO_INPUT_MODE,
+ - GPIO_OUTPUT_MODE,
+ - GPIO_INOUT_MODE.
+ Possible interrupt modes are:
+ - GPIO_IRQ_LEVEL_HIGH,
+ - GPIO_IRQ_LEVEL_LOW,
+ - GPIO_IRQ_EDGE_POSITIVE,
+ - GPIO_IRQ_EDGE_NEGATIVE,
+ - GPIO_IRQ_EDGE_BOTH
+
+ @return
+ none.
+
+ For example the following call will configure GPIO 4 as an input generating
+ interrupts on a low to high transition of the input:
+ @code
+ GPIO_config( &g_gpio, GPIO_4, GPIO_INPUT_MODE | GPIO_IRQ_EDGE_POSITIVE );
+ @endcode
+ */
+void GPIO_config
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint32_t config
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_set_outputs() function is used to set the state of the GPIO ports
+ configured as outputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param value
+ The value parameter specifies the state of the GPIO ports configured as
+ outputs. It is a bit mask of the form (GPIO_n_MASK | GPIO_m_MASK) where n
+ and m are numbers identifying GPIOs.
+ For example (GPIO_0_MASK | GPIO_1_MASK | GPIO_2_MASK ) specifies that the
+ first, second and third GPIOs' must be set high and all other outputs set
+ low.
+
+ @return
+ none.
+
+ Example 1:
+ Set GPIOs outputs 0 and 8 high and all other GPIO outputs low.
+ @code
+ GPIO_set_outputs( &g_gpio, GPIO_0_MASK | GPIO_8_MASK );
+ @endcode
+
+ Example 2:
+ Set GPIOs outputs 2 and 4 low without affecting other GPIO outputs.
+ @code
+ uint32_t gpio_outputs;
+ gpio_outputs = GPIO_get_outputs( &g_gpio );
+ gpio_outputs &= ~( GPIO_2_MASK | GPIO_4_MASK );
+ GPIO_set_outputs( &g_gpio, gpio_outputs );
+ @endcode
+
+ @see GPIO_get_outputs()
+ */
+void GPIO_set_outputs
+(
+ gpio_instance_t * this_gpio,
+ uint32_t value
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_set_output() function is used to set the state of a single GPIO
+ port configured as output.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter specifies the GPIO port that will have its output set
+ by a call to this function.
+
+ @param value
+ The value parameter specifies the desired state for the GPIO output. A value
+ of 0 will set the output low and a value of 1 will set the port high.
+
+ @return
+ none.
+ */
+void GPIO_set_output
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ uint8_t value
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_get_inputs() function is used to read the state of all GPIOs
+ confgured as inputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @return
+ This function returns a 32 bit unsigned integer where each bit represents
+ the state of an input. The least significant bit representing the state of
+ GPIO 0 and the most significant bit the state of GPIO 31.
+ */
+uint32_t GPIO_get_inputs
+(
+ gpio_instance_t * this_gpio
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_get_outputs() function is used to read the current state of all
+ GPIO outputs.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @return
+ This function returns a 32 bit unsigned integer where each bit represents
+ the state of an output. The least significant bit representing the state
+ of GPIO 0 and the most significant bit the state of GPIO 31.
+ */
+uint32_t GPIO_get_outputs
+(
+ gpio_instance_t * this_gpio
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_drive_inout() function is used to set the output state of a
+ GPIO configured as INOUT. An INOUT GPIO can be in one of three states:
+ - high
+ - low
+ - high impedance
+ An INOUT output would typically be used where several devices can drive the
+ state of a signal. The high and low states are equivalent to the high and low
+ states of a GPIO configured as output. The high impedance state is used to
+ prevent the GPIO from driving the state of the output and therefore allow
+ reading the state of the GPIO as an input.
+ Please note that the GPIO port you wish to use as INOUT through this function
+ must be configurable through software. Therefore the GPIO ports used as INOUT
+ must not have a fixed configuration selected as part of the hardware flow.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO for whcih this function will
+ change the output state.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @param inout_state
+ The inout_state parameter specifies the state of the I/O identified by the
+ first parameter. Possible states are:
+ - GPIO_DRIVE_HIGH,
+ - GPIO_DRIVE_LOW,
+ - GPIO_HIGH_Z (high impedance)
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_drive_inout() below will set the GPIO 7 output to
+ high impedance state.
+ @code
+ GPIO_drive_inout( &g_gpio, GPIO_7, GPIO_HIGH_Z );
+ @endcode
+ */
+void GPIO_drive_inout
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id,
+ gpio_inout_state_t inout_state
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_enable_irq() function is used to enable an interrupt to be
+ generated based on the state of the input identified as parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input the call to
+ GPIO_enable_irq() will enable to generate interrupts.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_enable_irq() below will allow GPIO 8 to generate
+ interrupts.
+ @code
+ GPIO_enable_irq( &g_gpio, GPIO_8 );
+ @endcode
+ */
+void GPIO_enable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_disable_irq() function is used to disable interrupt from being
+ generated based on the state of the input specified as parameter.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input the call to
+ GPIO_disable_irq() will disable from generating interrupts.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The call to GPIO_disable_irq() below will prevent GPIO 8 from generating
+ interrupts.
+ @code
+ GPIO_disable_irq( &g_gpio, GPIO_8 );
+ @endcode
+ */
+void GPIO_disable_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+/*-------------------------------------------------------------------------*//**
+ The GPIO_clear_irq() function is used to clear the interrupt generated by
+ the GPIO specified as parameter. The GPIO_clear_irq() function must be
+ called as part of a GPIO interrupt service routine (ISR) in order to prevent
+ the same interrupt event retriggering a call to the GPIO ISR.
+ Please note that interrupts may also need to be cleared in the processor's
+ interrupt controller.
+
+ @param this_gpio
+ The this_gpio parameter is a pointer to the gpio_instance_t structure holding
+ all data regarding the CoreGPIO instance controlled through this function call.
+
+ @param port_id
+ The port_id parameter identifies the GPIO input for which to clear the
+ interrupt.
+ An enumeration item of the form GPIO_n where n is the number of the GPIO
+ port is used to identify the GPIO port. For example GPIO_0 identifies the
+ first GPIO port and GPIO_31 the last one.
+
+ @return
+ none.
+
+ Example:
+ The example below demonstrates the use of the GPIO_clear_irq() function as
+ part of the GPIO 9 interrupt service routine on a Cortex-M processor.
+ @code
+ void GPIO9_IRQHandler( void )
+ {
+ do_interrupt_processing();
+
+ GPIO_clear_irq( &g_gpio, GPIO_9 );
+
+ NVIC_ClearPendingIRQ( GPIO9_IRQn );
+ }
+ @endcode
+ */
+void GPIO_clear_irq
+(
+ gpio_instance_t * this_gpio,
+ gpio_id_t port_id
+);
+
+#endif /* CORE_GPIO_H_ */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/coregpio_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/coregpio_regs.h
new file mode 100644
index 000000000..afbbfbcb8
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreGPIO/coregpio_regs.h
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 7964 $
+ * SVN $Date: 2015-10-09 18:26:53 +0530 (Fri, 09 Oct 2015) $
+ */
+#ifndef __CORE_GPIO_REGISTERS_H
+#define __CORE_GPIO_REGISTERS_H 1
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define IRQ_REG_OFFSET 0x80
+
+#define IRQ0_REG_OFFSET 0x80
+#define IRQ1_REG_OFFSET 0x84
+#define IRQ2_REG_OFFSET 0x88
+#define IRQ3_REG_OFFSET 0x8C
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define GPIO_IN_REG_OFFSET 0x90
+
+#define GPIO_IN0_REG_OFFSET 0x90
+#define GPIO_IN1_REG_OFFSET 0x94
+#define GPIO_IN2_REG_OFFSET 0x98
+#define GPIO_IN3_REG_OFFSET 0x9C
+
+/*------------------------------------------------------------------------------
+ *
+ */
+#define GPIO_OUT_REG_OFFSET 0xA0
+
+#define GPIO_OUT0_REG_OFFSET 0xA0
+#define GPIO_OUT1_REG_OFFSET 0xA4
+#define GPIO_OUT2_REG_OFFSET 0xA8
+#define GPIO_OUT3_REG_OFFSET 0xAC
+
+#endif /* __CORE_GPIO_REGISTERS_H */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.c
new file mode 100644
index 000000000..daa18879d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.c
@@ -0,0 +1,1563 @@
+/*******************************************************************************
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreI2C software driver implementation.
+ *
+ * SVN $Revision: 7984 $
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "cpu_types.h"
+#include "core_smbus_regs.h"
+#include "core_i2c.h"
+#include "hal.h"
+#include "hal_assert.h"
+
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * I2C transaction direction.
+ */
+#define WRITE_DIR 0u
+#define READ_DIR 1u
+
+/* -- TRANSACTIONS TYPES -- */
+#define NO_TRANSACTION 0u
+#define MASTER_WRITE_TRANSACTION 1u
+#define MASTER_READ_TRANSACTION 2u
+#define MASTER_RANDOM_READ_TRANSACTION 3u
+#define WRITE_SLAVE_TRANSACTION 4u
+#define READ_SLAVE_TRANSACTION 5u
+
+/* -- SMBUS H/W STATES -- */
+/* -- MASTER STATES -- */
+#define ST_BUS_ERROR 0x00u /* Bus error during MST or selected slave modes */
+#define ST_I2C_IDLE 0xF8u /* No activity and no interrupt either... */
+#define ST_START 0x08u /* start condition sent */
+#define ST_RESTART 0x10u /* repeated start */
+#define ST_SLAW_ACK 0x18u /* SLA+W sent, ack received */
+#define ST_SLAW_NACK 0x20u /* SLA+W sent, nack received */
+#define ST_TX_DATA_ACK 0x28u /* Data sent, ACK'ed */
+#define ST_TX_DATA_NACK 0x30u /* Data sent, NACK'ed */
+#define ST_LOST_ARB 0x38u /* Master lost arbitration */
+#define ST_SLAR_ACK 0x40u /* SLA+R sent, ACK'ed */
+#define ST_SLAR_NACK 0x48u /* SLA+R sent, NACK'ed */
+#define ST_RX_DATA_ACK 0x50u /* Data received, ACK sent */
+#define ST_RX_DATA_NACK 0x58u /* Data received, NACK sent */
+#define ST_RESET_ACTIVATED 0xD0u /* Master reset is activated */
+#define ST_STOP_TRANSMIT 0xE0u /* Stop has been transmitted */
+
+/* -- SLAVE STATES -- */
+#define ST_SLAVE_SLAW 0x60u /* SLA+W received */
+#define ST_SLAVE_SLAR_ACK 0xA8u /* SLA+R received, ACK returned */
+#define ST_SLV_LA 0x68u /* Slave lost arbitration */
+#define ST_GCA 0x70u /* GCA received */
+#define ST_GCA_LA 0x78u /* GCA lost arbitration */
+#define ST_RDATA 0x80u /* Data received */
+#define ST_SLA_NACK 0x88u /* Slave addressed, NACK returned */
+#define ST_GCA_ACK 0x90u /* Previously addresses with GCA, data ACKed */
+#define ST_GCA_NACK 0x98u /* GCA addressed, NACK returned */
+#define ST_RSTOP 0xA0u /* Stop received */
+#define ST_SLARW_LA 0xB0u /* Arbitration lost */
+#define ST_RACK 0xB8u /* Byte sent, ACK received */
+#define ST_SLAVE_RNACK 0xC0u /* Byte sent, NACK received */
+#define ST_FINAL 0xC8u /* Final byte sent, ACK received */
+#define ST_SLV_RST 0xD8u /* Slave reset state */
+
+
+/* I2C Channel base offset */
+#define CHANNEL_BASE_SHIFT 5u
+#define CHANNEL_MASK 0x1E0u
+
+/*
+ * Maximum address offset length in slave write-read transactions.
+ * A maximum of two bytes will be interpreted as address offset within the slave
+ * tx buffer.
+ */
+#define MAX_OFFSET_LENGTH 2u
+
+/*------------------------------------------------------------------------------
+ * I2C interrupts control functions implemented "i2c_interrupt.c".
+ * the implementation of these functions depend on the underlying hardware
+ * design and how the CoreI2C interrupt line is connected to the system's
+ * interrupt controller.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c );
+void I2C_disable_irq( i2c_instance_t * this_i2c );
+static void enable_slave_if_required(i2c_instance_t * this_i2c);
+
+/*------------------------------------------------------------------------------
+ * I2C_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ /*
+ * We need to disable ints while doing this as there is no guarantee we
+ * have not been called already and the ISR is active.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ /*
+ * Initialize all items of the this_i2c data structure to zero. This
+ * initializes all state variables to their init value. It relies on
+ * the fact that NO_TRANSACTION, I2C_SUCCESS and I2C_RELEASE_BUS all
+ * have an actual value of zero.
+ */
+ memset(this_i2c, 0, sizeof(i2c_instance_t));
+
+ /*
+ * Set base address of I2C hardware used by this instance.
+ */
+ this_i2c->base_address = base_address;
+
+ /*
+ * Update Serial address of the device
+ */
+ this_i2c->ser_address = ((uint_fast8_t)ser_address << 1u);
+
+ /*
+ * Configure hardware.
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x00); /* Reset I2C hardware. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c->base_address, CR0, ( clock_speed & 0x01) );
+
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS, this_i2c->ser_address);
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+
+ /*
+ * Finally safe to enable interrupts.
+ */
+
+ HAL_restore_interrupts( saved_psr );
+}
+/*------------------------------------------------------------------------------
+ * I2C_channel_init()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+)
+{
+ psr_t saved_psr;
+ uint_fast16_t clock_speed = (uint_fast16_t)ser_clock_speed;
+
+ HAL_ASSERT(channel_number < I2C_MAX_CHANNELS);
+ HAL_ASSERT(I2C_CHANNEL_0 != channel_number);
+
+ /*
+ * Cannot allow channel 0 in this function as we will trash the hardware
+ * base address and slave address.
+ */
+ if ((channel_number < I2C_MAX_CHANNELS) &&
+ (I2C_CHANNEL_0 != channel_number))
+ {
+ /*
+ * We need to disable ints while doing this as the hardware should already
+ * be active at this stage.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+ /*
+ * Initialize channel data.
+ */
+ memset(this_i2c_channel, 0, sizeof(i2c_instance_t));
+
+ this_i2c_channel->base_address =
+ ((this_i2c->base_address) & ~((addr_t)CHANNEL_MASK))
+ | (((addr_t)channel_number) << CHANNEL_BASE_SHIFT);
+
+ this_i2c_channel->ser_address = this_i2c->ser_address;
+
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x00); /* Reset I2C channel hardware. */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, ENS1, 0x01); /* set enable bit */
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR2, ( (clock_speed >> 2) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR1, ( (clock_speed >> 1) & 0x01) );
+ HAL_set_8bit_reg_field(this_i2c_channel->base_address, CR0, ( clock_speed & 0x01) );
+ /*
+ * Finally safe to enable interrupts.
+ */
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+
+ saved_psr=HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_WRITE_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_WRITE_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+ this_i2c->dir = WRITE_DIR;
+ this_i2c->master_tx_buffer = write_buffer;
+ this_i2c->master_tx_size = write_size;
+ this_i2c->master_tx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+
+ HAL_restore_interrupts(saved_psr);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+
+ saved_psr=HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = READ_DIR;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+ HAL_restore_interrupts( saved_psr );
+
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_write_read()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+)
+{
+ HAL_ASSERT(offset_size > 0u);
+ HAL_ASSERT(addr_offset != (uint8_t *)0);
+ HAL_ASSERT(read_size > 0u);
+ HAL_ASSERT(read_buffer != (uint8_t *)0);
+
+ this_i2c->master_status = I2C_FAILED;
+
+ if((read_size > 0u) && (offset_size > 0u))
+ {
+ psr_t saved_psr;
+ volatile uint8_t stat_ctrl;
+
+
+ saved_psr=HAL_disable_interrupts();
+
+ /* Update the transaction only when there is no transaction going on I2C */
+ if( this_i2c->transaction == NO_TRANSACTION)
+ {
+ this_i2c->transaction = MASTER_RANDOM_READ_TRANSACTION;
+ }
+
+ /* Update the Pending transaction information so that transaction can restarted */
+ this_i2c->pending_transaction = MASTER_RANDOM_READ_TRANSACTION ;
+
+ /* Update target address */
+ this_i2c->target_addr = (uint_fast8_t)serial_addr << 1u;
+
+ this_i2c->dir = WRITE_DIR;
+
+ this_i2c->master_tx_buffer = addr_offset;
+ this_i2c->master_tx_size = offset_size;
+ this_i2c->master_tx_idx = 0u;
+
+ this_i2c->master_rx_buffer = read_buffer;
+ this_i2c->master_rx_size = read_size;
+ this_i2c->master_rx_idx = 0u;
+
+ /* Set I2C status in progress */
+ this_i2c->master_status = I2C_IN_PROGRESS;
+ this_i2c->options = options;
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->is_transaction_pending = 1u;
+ }
+ else
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Clear interrupts if required (depends on repeated starts).
+ * Since the Bus is on hold, only then prior status needs to
+ * be cleared.
+ */
+ if ( I2C_HOLD_BUS == this_i2c->bus_status )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ stat_ctrl = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+ stat_ctrl = stat_ctrl; /* Avoids lint warning. */
+
+ /* Enable the interrupt. ( Re-enable) */
+ I2C_enable_irq( this_i2c );
+
+
+ HAL_restore_interrupts( saved_psr );
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_status()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ i2c_status_t i2c_status ;
+
+ i2c_status = this_i2c->master_status ;
+
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_wait_complete()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+)
+{
+ i2c_status_t i2c_status;
+ psr_t saved_psr;
+ /*
+ * Because we have no idea of what CPU we are supposed to be running on
+ * we need to guard this write to the timeout value to avoid ISR/user code
+ * interaction issues. Checking the status below should be fine as only a
+ * single byte should change in that.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+ this_i2c->master_timeout_ms = timeout_ms;
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Run the loop until state returns I2C_FAILED or I2C_SUCESS*/
+ do {
+ i2c_status = this_i2c->master_status;
+ } while(I2C_IN_PROGRESS == i2c_status);
+ return i2c_status;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_system_tick()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+)
+{
+ if(this_i2c->master_timeout_ms != I2C_NO_TIMEOUT)
+ {
+ if(this_i2c->master_timeout_ms > ms_since_last_tick)
+ {
+ this_i2c->master_timeout_ms -= ms_since_last_tick;
+ }
+ else
+ {
+ psr_t saved_psr;
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ /*
+ * Mark current transaction as having timed out.
+ */
+ this_i2c->master_status = I2C_TIMED_OUT;
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->is_transaction_pending = 0;
+
+
+ HAL_restore_interrupts( saved_psr );
+
+ /*
+ * Make sure we do not incorrectly signal a timeout for subsequent
+ * transactions.
+ */
+ this_i2c->master_timeout_ms = I2C_NO_TIMEOUT;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_tx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ this_i2c->slave_tx_buffer = tx_buffer;
+ this_i2c->slave_tx_size = tx_size;
+ this_i2c->slave_tx_idx = 0u;
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_rx_buffer()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ this_i2c->slave_rx_buffer = rx_buffer;
+ this_i2c->slave_rx_size = rx_size;
+ this_i2c->slave_rx_idx = 0u;
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_mem_offset_length()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+)
+{
+ HAL_ASSERT(offset_length <= MAX_OFFSET_LENGTH);
+
+ /*
+ * Single byte update, should be interrupt safe
+ */
+ if(offset_length > MAX_OFFSET_LENGTH)
+ {
+ this_i2c->slave_mem_offset_length = MAX_OFFSET_LENGTH;
+ }
+ else
+ {
+ this_i2c->slave_mem_offset_length = offset_length;
+ }
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_register_write_handler()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * shared data without the I2C ISR interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ this_i2c->slave_write_handler = handler;
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register and slave mode flag without the I2C ISR interrupting
+ * us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ /* Set the Assert Acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Enable slave mode */
+ this_i2c->is_slave_enabled = 1u;
+
+
+ HAL_restore_interrupts( saved_psr );
+
+ /* Enable I2C IRQ*/
+ I2C_enable_irq( this_i2c );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the I2C ISR interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ /* Reset the assert acknowledge bit. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+
+ /* Disable slave mode with IRQ blocked to make whole change atomic */
+ this_i2c->is_slave_enabled = 0u;
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void enable_slave_if_required
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This function is only called from within the ISR and so does not need
+ * guarding on the register access.
+ */
+ if( 0 != this_i2c->is_slave_enabled )
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+}
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+)
+{
+ uint8_t second_slave_address;
+
+ /*
+ This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ With the programmable configuration, ADDR1[0] and ADDR0[0] both control
+ enable/disable of GCA recognition, as an effective OR of the 2 bit fields.
+ Therefore we set ADDR1[0] to 0 here, so that only ADDR0[0] controls GCA.
+ */
+ second_slave_address = (uint8_t)((second_slave_addr << 1u) & (~SLAVE1_EN_MASK));
+
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, second_slave_address);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_slave_second_addr()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ We are disabling the second slave address by setting the value of the 2nd
+ slave address to the primary slave address. The reason for using this method
+ of disabling 2nd slave address is that ADDRESS1[0] has different meaning
+ depending on hardware configuration. Its use would likely interfere with
+ the intended GCA setting.
+ */
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ HAL_set_8bit_reg(this_i2c->base_address, ADDRESS1, this_i2c->ser_address);
+}
+
+/*------------------------------------------------------------------------------
+ * i2C_set_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* accept GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x01u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_gca()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * This read modify write access should be interrupt safe as the address
+ * register is not written to in the ISR.
+ */
+ /* Clear GC addressing. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, GC, 0x00u);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_isr()
+ * See "core_i2c.h" for details of how to use this function.
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+)
+{
+ volatile uint8_t status;
+ uint8_t data;
+ uint8_t hold_bus;
+ uint8_t clear_irq = 1u;
+
+ status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+
+ switch( status )
+ {
+ /************** MASTER TRANSMITTER / RECEIVER *******************/
+
+ case ST_START: /* start has been xmt'd */
+ case ST_RESTART: /* repeated start has been xmt'd */
+ //write_hex(STDOUT_FILENO, status);
+ HAL_set_8bit_reg_field( this_i2c->base_address, STA, 0x00u);
+ HAL_set_8bit_reg( this_i2c->base_address, DATA, this_i2c->target_addr); /* write call address */
+ HAL_set_8bit_reg_field( this_i2c->base_address, DIR, this_i2c->dir); /* set direction bit */
+ if(this_i2c->dir == WRITE_DIR)
+ {
+ this_i2c->master_tx_idx = 0u;
+ }
+ else
+ {
+ this_i2c->master_rx_idx = 0u;
+ }
+
+ /*
+ * Clear the pending transaction. This condition will be true if the slave
+ * has acquired the bus to carry out pending master transaction which
+ * it had received during its slave transmission or reception mode.
+ */
+ if(this_i2c->is_transaction_pending)
+ {
+ this_i2c->is_transaction_pending = 0u;
+ }
+
+ /*
+ * Make sure to update proper transaction after master START
+ * or RESTART
+ */
+ if(this_i2c->transaction != this_i2c->pending_transaction)
+ {
+ this_i2c->transaction = this_i2c->pending_transaction;
+ }
+ break;
+
+ case ST_LOST_ARB:
+ /* Set start bit. Let's keep trying! Don't give up! */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ break;
+
+ case ST_STOP_TRANSMIT:
+ /* Stop has been transmitted. Do nothing */
+ break;
+
+ /******************* MASTER TRANSMITTER *************************/
+ case ST_SLAW_NACK:
+ //write_hex(STDOUT_FILENO, status);
+ /* SLA+W has been transmitted; not ACK has been received - let's stop. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_SLAW_ACK:
+ case ST_TX_DATA_ACK:
+ //write_hex(STDOUT_FILENO, status);
+ /* data byte has been xmt'd with ACK, time to send stop bit or repeated start. */
+ if (this_i2c->master_tx_idx < this_i2c->master_tx_size)
+ {
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->master_tx_buffer[this_i2c->master_tx_idx++]);
+ }
+ else if ( this_i2c->transaction == MASTER_RANDOM_READ_TRANSACTION )
+ {
+ /* We are finished sending the address offset part of a random read transaction.
+ * It is is time to send a restart in order to change direction. */
+ this_i2c->dir = READ_DIR;
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ else /* done sending. let's stop */
+ {
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ this_i2c->master_status = I2C_SUCCESS;
+ }
+ break;
+
+ case ST_TX_DATA_NACK:
+ //write_hex(STDOUT_FILENO, status);
+ /* data byte SENT, ACK to be received
+ * In fact, this means we've received a NACK (This may not be
+ * obvious, but if we've rec'd an ACK then we would be in state
+ * 0x28!) hence, let's send a stop bit
+ */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);/* xmt stop condition */
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ /********************* MASTER (or slave?) RECEIVER *************************/
+
+ /* STATUS codes 08H, 10H, 38H are all covered in MTX mode */
+ case ST_SLAR_ACK: /* SLA+R tx'ed. */
+// //write_hex(STDOUT_FILENO, status);
+ /* Let's make sure we ACK the first data byte received (set AA bit in CTRL) unless
+ * the next byte is the last byte of the read transaction.
+ */
+ if(this_i2c->master_rx_size > 1u)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ }
+ else if(1u == this_i2c->master_rx_size)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ else /* this_i2c->master_rx_size == 0u */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_SUCCESS;
+ this_i2c->transaction = NO_TRANSACTION;
+ }
+ break;
+
+ case ST_SLAR_NACK: /* SLA+R tx'ed; let's release the bus (send a stop condition) */
+// //write_hex(STDOUT_FILENO, status);
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u);
+ this_i2c->master_status = I2C_FAILED;
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ enable_slave_if_required(this_i2c);
+ break;
+
+ case ST_RX_DATA_ACK: /* Data byte received, ACK returned */
+// //write_hex(STDOUT_FILENO, status);
+ /* First, get the data */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx++] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ if( this_i2c->master_rx_idx >= (this_i2c->master_rx_size - 1u))
+ {
+ /* If we're at the second last byte, let's set AA to 0 so
+ * we return a NACK at the last byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RX_DATA_NACK: /* Data byte received, NACK returned */
+// //write_hex(STDOUT_FILENO, status);
+ /* Get the data, then send a stop condition */
+ this_i2c->master_rx_buffer[this_i2c->master_rx_idx] = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+
+ hold_bus = this_i2c->options & I2C_HOLD_BUS;
+
+ /* Store the information of current I2C bus status in the bus_status*/
+ this_i2c->bus_status = hold_bus;
+ if ( hold_bus == 0u )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STO, 0x01u); /*xmt stop condition */
+
+ /* Bus is released, now we can start listening to bus, if it is slave */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ I2C_disable_irq( this_i2c );
+ clear_irq = 0u;
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->master_status = I2C_SUCCESS;
+ break;
+
+ /******************** SLAVE RECEIVER **************************/
+ case ST_GCA_NACK: /* NACK after, GCA addressing */
+ case ST_SLA_NACK: /* Re-enable AA (assert ack) bit for future transmissions */
+ //write_hex(STDOUT_FILENO, status);
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ this_i2c->transaction = NO_TRANSACTION;
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ break;
+
+ case ST_GCA_LA: /* Arbitr. lost (GCA rec'd) */
+ case ST_SLV_LA: /* Arbitr. lost (SLA rec'd) */
+ //write_hex(STDOUT_FILENO, status);
+ /*
+ * We lost arbitration and either the GCE or our address was the
+ * one received so pend the master operation we were starting.
+ */
+ this_i2c->is_transaction_pending = 1u;
+ /* Fall through to normal ST processing as we are now in slave mode */
+
+ case ST_GCA: /* General call address received, ACK returned */
+ case ST_SLAVE_SLAW: /* SLA+W received, ACK returned */
+ //write_hex(STDOUT_FILENO, status);
+ this_i2c->transaction = WRITE_SLAVE_TRANSACTION;
+ this_i2c->slave_rx_idx = 0u;
+ this_i2c->random_read_addr = 0u;
+ /*
+ * If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ /* Fall through to put address as first byte in payload buffer */
+#else
+ /* Only break from this case if the slave address must NOT be included at the
+ * beginning of the received write data. */
+ break;
+#endif
+ case ST_GCA_ACK: /* DATA received; ACK sent after GCA */
+ case ST_RDATA: /* DATA received; must clear DATA register */
+ //write_hex(STDOUT_FILENO, status);
+ if((this_i2c->slave_rx_buffer != (uint8_t *)0)
+ && (this_i2c->slave_rx_idx < this_i2c->slave_rx_size))
+ {
+ data = HAL_get_8bit_reg(this_i2c->base_address, DATA);
+ this_i2c->slave_rx_buffer[this_i2c->slave_rx_idx++] = data;
+
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ if((ST_RDATA == status) || (ST_GCA_ACK == status))
+ {
+ /* Ignore the slave address byte in the random read address
+ computation in the case where INCLUDE_SLA_IN_RX_PAYLOAD
+ is defined. */
+#endif
+ this_i2c->random_read_addr = (this_i2c->random_read_addr << 8) + data;
+#ifdef INCLUDE_SLA_IN_RX_PAYLOAD
+ }
+#endif
+ }
+
+ if(this_i2c->slave_rx_idx >= this_i2c->slave_rx_size)
+ {
+ /* Rx buffer is full. NACK next received byte. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ }
+ break;
+
+ case ST_RSTOP:
+ //write_hex(STDOUT_FILENO, status);
+ /* STOP or repeated START occurred. */
+ /* We cannot be sure if the transaction has actually completed as
+ * this hardware state reports that either a STOP or repeated START
+ * condition has occurred. We assume that this is a repeated START
+ * if the transaction was a write from the master to this point.*/
+ if ( this_i2c->transaction == WRITE_SLAVE_TRANSACTION )
+ {
+ if ( this_i2c->slave_rx_idx == this_i2c->slave_mem_offset_length )
+ {
+ this_i2c->slave_tx_idx = this_i2c->random_read_addr;
+ }
+ /* Call the slave's write transaction handler if it exists. */
+ if ( this_i2c->slave_write_handler != 0u )
+ {
+ i2c_slave_handler_ret_t h_ret;
+ h_ret = this_i2c->slave_write_handler( this_i2c, this_i2c->slave_rx_buffer, (uint16_t)this_i2c->slave_rx_idx );
+ if ( I2C_REENABLE_SLAVE_RX == h_ret )
+ {
+ /* There is a small risk that the write handler could
+ * call I2C_disable_slave() but return
+ * I2C_REENABLE_SLAVE_RX in error so we only enable
+ * ACKs if still in slave mode. */
+ enable_slave_if_required(this_i2c);
+ }
+ else
+ {
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x0u );
+ /* Clear slave mode flag as well otherwise in mixed
+ * master/slave applications, the AA bit will get set by
+ * subsequent master operations. */
+ this_i2c->is_slave_enabled = 0u;
+ }
+ }
+ else
+ {
+ /* Re-enable address acknowledge in case we were ready to nack the next received byte. */
+ HAL_set_8bit_reg_field( this_i2c->base_address, AA, 0x01u );
+ }
+ }
+ else /* A stop or repeated start outside a write/read operation */
+ {
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * See if we need to re-enable acknowledgement as some error conditions, such
+ * as a master prematurely ending a transfer, can see us get here with AA set
+ * to 0 which will disable slave operation if we are not careful.
+ */
+ enable_slave_if_required(this_i2c);
+ }
+
+ /* Mark any previous master write transaction as complete. */
+ this_i2c->slave_status = I2C_SUCCESS;
+
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ case ST_SLV_RST: /* SMBUS ONLY: timeout state. must clear interrupt */
+ //write_hex(STDOUT_FILENO, status);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear status to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ enable_slave_if_required(this_i2c); /* Make sure AA is set correctly */
+
+ break;
+
+ /****************** SLAVE TRANSMITTER **************************/
+ case ST_SLAVE_SLAR_ACK: /* SLA+R received, ACK returned */
+ case ST_SLARW_LA: /* Arbitration lost, and: */
+ case ST_RACK: /* Data tx'ed, ACK received */
+ //write_hex(STDOUT_FILENO, status);
+ if ( status == ST_SLAVE_SLAR_ACK )
+ {
+ this_i2c->transaction = READ_SLAVE_TRANSACTION;
+ this_i2c->random_read_addr = 0u;
+ this_i2c->slave_status = I2C_IN_PROGRESS;
+ /* If Start Bit is set clear it, but store that information since it is because of
+ * pending transaction
+ */
+ if(HAL_get_8bit_reg_field(this_i2c->base_address, STA))
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ this_i2c->is_transaction_pending = 1u;
+ }
+ }
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size)
+ {
+ /* Ensure 0xFF is returned to the master when the slave specifies
+ * an empty transmit buffer. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, 0xFFu);
+ }
+ else
+ {
+ /* Load the data the data byte to be sent to the master. */
+ HAL_set_8bit_reg(this_i2c->base_address, DATA, (uint_fast8_t)this_i2c->slave_tx_buffer[this_i2c->slave_tx_idx++]);
+ }
+ /* Determine if this is the last data byte to send to the master. */
+ if (this_i2c->slave_tx_idx >= this_i2c->slave_tx_size) /* last byte? */
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x00u);
+ /* Next read transaction will result in slave's transmit buffer
+ * being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ }
+ break;
+
+ case ST_SLAVE_RNACK: /* Data byte has been transmitted; not-ACK has been received. */
+ case ST_FINAL: /* Last Data byte tx'ed, ACK received */
+ //write_hex(STDOUT_FILENO, status);
+ /* We assume that the transaction will be stopped by the master.
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte. */
+ this_i2c->slave_tx_idx = 0u;
+ HAL_set_8bit_reg_field(this_i2c->base_address, AA, 0x01u);
+
+ /* Mark previous state as complete */
+ this_i2c->slave_status = I2C_SUCCESS;
+ /* Check if transaction was pending. If yes, set the START bit */
+ if(this_i2c->is_transaction_pending)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x01u);
+ }
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+
+ break;
+
+ /* Master Reset has been activated Wait 35 ms for interrupt to be set,
+ * clear interrupt and proceed to 0xF8 state. */
+ case ST_RESET_ACTIVATED:
+ case ST_BUS_ERROR: /* Bus error during MST or selected slave modes */
+ default:
+ //write_hex(STDOUT_FILENO, status);
+ /* Some undefined state has encountered. Clear Start bit to make
+ * sure, next good transaction happen */
+ HAL_set_8bit_reg_field(this_i2c->base_address, STA, 0x00u);
+ /*
+ * Set the transaction back to NO_TRANSACTION to allow user to do further
+ * transaction.
+ */
+ this_i2c->transaction = NO_TRANSACTION;
+ /*
+ * Reset slave_tx_idx so that a subsequent read will result in the slave's
+ * transmit buffer being sent from the first byte.
+ */
+ this_i2c->slave_tx_idx = 0u;
+ /*
+ * Clear statuses to I2C_FAILED only if there was an operation in progress.
+ */
+ if(I2C_IN_PROGRESS == this_i2c->master_status)
+ {
+ this_i2c->master_status = I2C_FAILED;
+ }
+
+ if(I2C_IN_PROGRESS == this_i2c->slave_status)
+ {
+ this_i2c->slave_status = I2C_FAILED;
+ }
+
+ break;
+ }
+
+ if ( clear_irq )
+ {
+ /* clear interrupt. */
+ HAL_set_8bit_reg_field(this_i2c->base_address, SI, 0x00u);
+ }
+
+ /* Read the status register to ensure the last I2C registers write took place
+ * in a system built around a bus making use of posted writes. */
+// status = HAL_get_8bit_reg( this_i2c->base_address, STATUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_smbus_init()
+ * See "i2c.h" for details of how to use this function.
+ */
+
+/*
+ * SMBSUS_NO = 1
+ * SMBALERT_NO = 1
+ * SMBus enable = 1
+ */
+#define INIT_AND_ENABLE_SMBUS 0x54u
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+)
+{
+ /*
+ * Single byte register write, should be interrupt safe
+ */
+ /* Enable SMBUS */
+ HAL_set_8bit_reg(this_i2c->base_address, SMBUS, INIT_AND_ENABLE_SMBUS);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_enable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x01u);
+ }
+ if ( irq_type & I2C_SMBSUS_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x01u);
+ }
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_disable_smbus_irq()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ if ( irq_type & I2C_SMBALERT_IRQ)
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_IE, 0x00u);
+ }
+ if (irq_type & I2C_SMBSUS_IRQ )
+ {
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_IE, 0x00u);
+ }
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_suspend_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x00u);
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_resume_smbus_slave()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBSUS_NO_CONTROL, 0x01u);
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_reset_smbus()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBUS_MST_RESET, 0x01u);
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x00u);
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_clear_smbus_alert()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+)
+{
+ psr_t saved_psr;
+
+ /*
+ * We need to disable interrupts here to ensure we can update the
+ * hardware register without the SMBUS IRQs interrupting us.
+ */
+
+ saved_psr=HAL_disable_interrupts();
+
+ HAL_set_8bit_reg_field(this_i2c->base_address, SMBALERT_NO_CONTROL, 0x01u);
+
+
+ HAL_restore_interrupts( saved_psr );
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_irq_status()
+ * See "i2c.h" for details of how to use this function.
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+)
+{
+ uint8_t status ;
+ uint8_t irq_type = I2C_NO_IRQ ;
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, SMBUS);
+
+ if( status & (uint8_t)SMBALERT_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBALERT_IRQ ;
+ }
+
+ if( status & (uint8_t)SMBSUS_NI_STATUS_MASK )
+ {
+ irq_type |= I2C_SMBSUS_IRQ ;
+ }
+
+ status = HAL_get_8bit_reg(this_i2c->base_address, CONTROL);
+
+ if( status & (uint8_t)SI_MASK )
+ {
+ irq_type |= I2C_INTR_IRQ ;
+ }
+ return(irq_type);
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_set_slave_addr2()
+ * See "i2c.h" for details of how to use this function.
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+)
+{
+ this_i2c->p_user_data = p_user_data ;
+}
+
+/*------------------------------------------------------------------------------
+ * I2C_get_user_data()
+ * See "i2c.h" for details of how to use this function.
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+)
+{
+ return( this_i2c->p_user_data);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.h
new file mode 100644
index 000000000..2b1d5acab
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_i2c.h
@@ -0,0 +1,2280 @@
+/*******************************************************************************
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreI2C software driver Application Programming Interface.
+ * This file contains defines and function declarations allowing to interface
+ * with the CoreI2C software driver.
+ *
+ * SVN $Revision: 7984 $
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $
+ */
+/*=========================================================================*//**
+ @mainpage CoreI2C Bare Metal Driver.
+ The CoreI2C bare metal software driver supports I2C master and slave
+ operations.
+
+ @section intro_sec Introduction
+ The CoreI2C driver provides a set of functions for controlling the Microsemi
+ CoreI2C hardware IP. The driver supports up to 16 separate I2C channels per
+ CoreI2C instance, with common slave address settings shared between channels
+ on a device.
+
+ Optional features of the CoreI2C allow it operate with I2C based protocols
+ such as System Management Bus (SMBus), Power Management Bus (PMBus) and
+ Intelligent Platform Management Interface (IPMI). This driver provides support
+ for these features when enabled in the CoreI2C IP.
+
+ The major features provided by CoreI2C driver are:
+ - Support for configuring the I2C channels of each CoreI2C peripheral.
+ - I2C master operations.
+ - I2C slave operations.
+ - SMBus related operations.
+
+ This driver can be used as part of a bare metal system where no operating
+ system is available. The driver can be adapted for use as part of an
+ operating system, but the implementation of the adaptation layer between the
+ driver and the operating system's driver model is outside the scope of this
+ driver.
+
+ @section hw_dependencies Hardware Flow Dependencies
+ Your application software should configure the CoreI2C driver through
+ calls to the I2C_init() function for each CoreI2C instance in the
+ hardware design. The configuration parameters include the CoreI2C hardware
+ instance base address and other runtime parameters, such as the I2C serial
+ clock frequency and I2C device address.
+
+ Once channel 0 of a CoreI2C peripheral has been initialized via I2C_init(),
+ any additional channels present should be configured by calling
+ I2C_channel_init() for each of the remaining channels.
+
+ No CoreI2C hardware configuration parameters are used by the driver, apart
+ from the CoreI2C hardware instance base address. Hence, no additional
+ configuration files are required to use the driver.
+
+ Interrupt Control
+ The CoreI2C driver has to enable and disable the generation of interrupts by
+ CoreI2C at various times when it is operating. This enabling and disabling of
+ interrupts must be done through the system’s interrupt controller. For that
+ reason, the method of controlling the CoreI2C interrupt is system specific
+ and it is necessary to customize the I2C_enable_irq() and I2C_disable_irq()
+ functions. These functions are found in the file i2c_interrupt.c. Their
+ default implementation fires an assertion to attract attention to the fact
+ that these functions must be modified.
+
+ The implementation of the I2C_enable_irq() function should permit interrupts
+ generated by a CoreI2C instance to interrupt the processor. The implementation
+ of the I2C_disable_irq() function should prevent interrupts generated by a
+ CoreI2C instance from interrupting the processor. Please refer to the provided
+ example projects for a working implementation of these functions.
+
+ The function I2C_register_write_handler() is used to register a write handler
+ function with the CoreI2C driver that it calls on completion of an I2C write
+ transaction by the CoreI2C slave. It is your responsibility to create and
+ register the implementation of this handler function that processes or
+ trigger the processing of the received data.
+
+ The SMBSUS and SMBALERT interrupts are related to the SMBus interface and are
+ enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. It is your responsibility to create
+ interrupt handler functions in your application to get the desired response
+ for the SMBus interrupts.
+
+ Note: You must include the path to any application header files that are
+ included in the i2c_interrupt.c file, as an include path in your
+ project’s compiler settings. The details of how to do this will depend
+ on your development software.
+
+ SMBus Logic options
+ SMBus related APIs will not have any effect if in CoreI2C hardware
+ configuration "Generate SMBus Logic" is not enabled. The APIs which will not
+ give desired results in case SMBus Logic is disabled are:
+
+ I2C_smbus_init()
+ I2C_reset_smbus()
+ I2C_enable_smbus_irq()
+ I2C_disable_smbus_irq()
+ I2C_suspend_smbus_slave()
+ I2C_resume_smbus_slave()
+ I2C_set_smsbus_alert()
+ I2C_clear_smsbus_alert()
+ I2C_get_irq_status()
+
+ Fixed Baud Rate Values
+ The serial clock frequency parameter passed to the I2C_init() and
+ I2C_channel_init() functions may not have any effect if fixed values were
+ selected for Baud rate in the hardware configuration of CoreI2C. When fixed
+ values are selected for these baud rates, the driver cannot overwrite
+ the fixed values.
+
+ Fixed Slave Address Options Values
+ The primary slave address parameter passed to the I2C_init() function, and
+ secondary address value passed to the I2C_set_slave_second_addr() function,
+ may not have the desired effect if fixed values were selected for the slave 0
+ address and slave 1 address respectively. Proper operation of this version of
+ the driver requires the slave addresses to be programmable.
+
+ @section theory_op Theory of Operation
+ The CoreI2C software driver is designed to allow the control of multiple
+ instances of CoreI2C with one or more I2C channels. Each channel in an
+ instance of CoreI2C in the hardware design is associated with a single
+ instance of the i2c_instance_t structure in the software. You must allocate
+ memory for one unique i2c_instance_t structure instance for each channel of
+ each CoreI2C hardware instance. The contents of these data structures are
+ initialised during calls to I2C_init() and if necessary I2C_channel_init().
+ A pointer to the structure is passed to subsequent driver functions in order
+ to identify the CoreI2C hardware instance and channel you wish to perform the
+ requested operation.
+
+ Note: Do not attempt to directly manipulate the contents of i2c_instance_t
+ structures. These structures are only intended to be modified by the driver
+ functions.
+
+ The CoreI2C driver functions are grouped into the following categories:
+ - Initialization and configuration functions
+ - Interrupt control
+ - I2C slave addressing functions
+ - I2C master operations functions to handle write, read and write-read
+ transactions
+ - I2C slave operations functions to handle write, read and write-read
+ transactions
+ - Mixed master-slave operations
+ - SMBus interface configuration and control.
+
+ Initialization and Configuration
+ The CoreI2C device is first initialized through a call to the I2C_init()
+ function. Since each CoreI2C peripheral supports up to 16 channels, an
+ additional function, I2C_channel_init(), is required to initialize the
+ remaining channels with their own data structures.
+
+ I2C_init() initializes channel 0 of a CoreI2C and the i2c_instance_t for
+ channel 0 acts as the basis for further channel initialization as the
+ hardware base address and I2C serial address are same across all the
+ channels. I2C_init() must be called before any other I2C driver function
+ calls. The I2C_init() call for each CoreI2C takes the I2C serial address
+ assigned to the I2C and the serial clock divider to be used to generate its
+ I2C clock as configuration parameters.
+
+ I2C_channel_init() takes as input parameters a pointer to the CoreI2C
+ i2c_instance_t which has been initialized via I2C_init() and a pointer to a
+ separate i2c_instance_t which represents this new channel. Another input
+ parameter which is required by this function is serial clock divider which
+ generates its I2C clock.
+
+ Interrupt Control
+ The CoreI2C driver is interrupt driven and it uses each channels INT
+ interrupt to drive the state machine which is at the heart of the driver.
+ The application is responsible for providing the link between the interrupt
+ generating hardware and the CoreI2C interrupt handler and must ensure that
+ the I2C_isr() function is called with the correct i2c_instance_t structure
+ pointer for the CoreI2C channel initiating the interrupt.
+
+ The driver enables and disables the generation of INT interrupts by CoreI2C
+ at various times when it is operating through the user supplied
+ I2C_enable_irq() and I2C_disable_irq() functions.
+
+ The function I2C_register_write_handler() is used to register a write
+ handler function with the CoreI2C driver which is called on completion
+ of an I2C write transaction by the CoreI2C slave. It is the user
+ applications responsibility to create and register the implementation of
+ this handler function that processes or triggers the processing of the
+ received data.
+
+ The other two interrupt sources in the CoreI2C, are related to SMBus
+ operation and are enabled and disabled through I2C_enable_smbus_irq() and
+ I2C_disable_smbus_irq() respectively. Due to the application specific
+ nature of the response to SMBus interrupts, you must design interrupt
+ handler functions in the application to get the desired behaviour for
+ SMBus related interrupts.
+
+ If enabled, the SMBA_INT signal from the CoreI2C is asserted if an
+ SMBALERT condition is signalled on the SMBALERT_NI input for the channel.
+
+ If enabled, the SMBS_INT signal from the CoreI2C is asserted if an
+ SMBSUSPEND condition is signalled on the SMBSUS_NI input for the channel.
+
+ I2C slave addressing functions
+ A CoreI2C peripheral can respond to three slave addresses:
+ - Slave address 0 - This is the primary slave address which is used for
+ accessing a CoreI2C channel when it acts as a slave in
+ I2C transactions. You must configure the primary slave
+ address via I2C_init().
+
+ - Slave address 1 - This is the secondary slave address which might be
+ required in certain application specific scenarios.
+ The secondary slave address can be configured via
+ I2C_set_slave_second_addr() and disabled via
+ I2C_disable_slave_second_addr().
+
+ - General call address - A CoreI2C slave can be configured to respond to
+ a broadcast command by a master transmitting the
+ general call address of 0x00. Use the I2C_set_gca()
+ function to enable the slave to respond to the general
+ call address. If the CoreI2C slave is not required to
+ respond to the general call address, disable this
+ address by calling I2C_clear_gca().
+
+ Note: All channels on a CoreI2C instance share the same slave address logic.
+ This means that they cannot have separate slave addresses and rely on
+ the separate physical I2C bus connections to distinguish them.
+
+ Transaction Types
+ The I2C driver is designed to handle three types of I2C transaction:
+ Write transactions
+ Read transactions
+ Write-read transactions
+
+ Write transaction
+ The master I2C device initiates a write transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges the
+ receipt of it's address with an acknowledge bit. The master sends data one
+ byte at a time to the slave, which must acknowledge receipt of each byte
+ for the next byte to be sent. The master sends a STOP bit to complete the
+ transaction. The slave can abort the transaction by replying with a
+ non-acknowledge bit instead of an acknowledge.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ Read transaction
+ The master I2C device initiates a read transaction by sending a START bit
+ as soon as the bus becomes free. The START bit is followed by the 7-bit
+ serial address of the target slave device followed by the read/write bit
+ indicating the direction of the transaction. The slave acknowledges
+ receipt of it's slave address with an acknowledge bit. The slave sends
+ data one byte at a time to the master, which must acknowledge receipt of
+ each byte for the next byte to be sent. The master sends a non-acknowledge
+ bit following the last byte it wishes to read followed by a STOP bit.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ Write-read transaction
+ The write-read transaction is a combination of a write transaction
+ immediately followed by a read transaction. There is no STOP bit between
+ the write and read phases of a write-read transaction. A repeated START
+ bit is sent between the write and read phases.
+
+ Whilst the write handler is being executed, the slave holds the clock line
+ low to stretch the clock until the response is ready.
+
+ The write-read transaction is typically used to send a command or offset
+ in the write transaction specifying the logical data to be transferred
+ during the read phase.
+
+ The application programmer can choose not to send a STOP bit at the end of
+ the transaction causing the next transaction to begin with a repeated
+ START bit.
+
+ Master Operations
+ The application can use the I2C_write(), I2C_read() and I2C_write_read()
+ functions to initiate an I2C bus transaction. The application can then wait
+ for the transaction to complete using the I2C_wait_complete() function
+ or poll the status of the I2C transaction using the I2C_get_status()
+ function until it returns a value different from I2C_IN_PROGRESS. The
+ I2C_system_tick() function can be used to set a time base for the
+ I2C_wait_complete() function’s time out delay.
+
+ Slave Operations
+ The configuration of the I2C driver to operate as an I2C slave requires
+ the use of the following functions:
+ I2C_set_slave_tx_buffer()
+ I2C_set_slave_rx_buffer()
+ I2C_set_slave_mem_offset_length()
+ I2C_register_write_handler()
+ I2C_enable_slave()
+
+ Use of all functions is not required if the slave I2C does not need to support
+ all types of I2C read transactions. The subsequent sections list the functions
+ that must be used to support each transaction type.
+
+ Responding to read transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to I2C read transactions:
+ I2C_set_slave_tx_buffer()
+ I2C_enable_slave()
+
+ The function I2C_set_slave_tx_buffer() specifies the data buffer that
+ will be transmitted when the I2C slave is the target of an I2C read
+ transaction. It is then up to the application to manage the content of
+ that buffer to control the data that will be transmitted to the I2C
+ master as a result of the read transaction.
+
+ The function I2C_enable_slave() enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ Responding to write transactions
+ The following functions are used to configure the I2C driver to respond
+ to I2C write transactions:
+ I2C_set_slave_rx_buffer()
+ I2C_register_write_handler()
+ I2C_enable_slave()
+
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that
+ will be used to store the data received by the I2C slave when it is the
+ target an I2C write transaction.
+
+ The function I2C_register_write_handler() specifies the handler function
+ that must be called on completion of the I2C write transaction. It is this
+ handler function that processes or triggers the processing of the received
+ data.
+
+ The function I2C_enable_slave() enables the I2C hardware instance
+ to respond to I2C transactions. It must be called after the I2C driver
+ has been configured to respond to the required transaction types.
+
+ Responding to write-read transactions
+ The following functions are used to configure the CoreI2C driver to
+ respond to write-read transactions:
+ I2C_set_slave_mem_offset_length()
+ I2C_set_slave_tx_buffer()
+ I2C_set_slave_rx_buffer()
+ I2C_register_write_handler()
+ I2C_enable_slave()
+
+ The function I2C_set_slave_mem_offset_length() specifies the number of
+ bytes expected by the I2C slave during the write phase of the write-read
+ transaction.
+
+ The function I2C_set_slave_tx_buffer() specifies the data that will be
+ transmitted to the I2C master during the read phase of the write-read
+ transaction. The value received by the I2C slave during the write phase of
+ the transaction will be used as an index into the transmit buffer
+ specified by this function to decide which part of the transmit buffer
+ will be transmitted to the I2C master as part of the read phase of the
+ write-read transaction.
+
+ The function I2C_set_slave_rx_buffer() specifies the data buffer that
+ will be used to store the data received by the I2C slave during the write
+ phase of the write-read transaction. This buffer must be at least large
+ enough to accommodate the number of bytes specified through the
+ I2C_set_slave_mem_offset_length() function.
+
+ The function I2C_register_write_handler() can optionally be used to
+ specify a handler function that is called on completion of the write phase
+ of the I2C write-read transaction. If a handler function is registered, it
+ is responsible for processing the received data in the slave receive
+ buffer and populating the slave transmit buffer with the data that will be
+ transmitted to the I2C master as part of the read phase of the write-read
+ transaction.
+
+ The function I2C_enable_slave() enables the CoreI2C hardware instance to
+ respond to I2C transactions. It must be called after the CoreI2C driver
+ has been configured to respond to the required transaction types.
+
+ Mixed Master-Slave Operations
+ The CoreI2C device supports mixed master and slave operations. If the
+ CoreI2C slave has a transaction in progress and your application attempts to
+ begin a master mode transaction, the CoreI2C driver queu3es the master mode
+ transaction until the bus is released and the CoreI2C can switch to master
+ mode and acquire the bus. The CoreI2C master then starts the previously
+ queued master transaction.
+
+ SMBus Control
+ The CoreI2C driver enables the CoreI2C peripheral’s SMBus functionality
+ using the I2C_smbus_init() function.
+
+ The I2C_suspend_smbus_slave() function is used, with a master mode CoreI2C,
+ to force slave devices on the SMBus to enter their power-down/suspend mode.
+ The I2C_resume_smbus_slave() function is used to end the suspend operation
+ on the SMBus.
+
+ The I2C_reset_smbus() function is used, with a master mode CoreI2C, to force
+ all devices on the SMBus to reset their SMBUs interface.
+
+ The I2C_set_smsbus_alert() function is used, by a slave mode CoreI2C, to
+ force communication with the SMBus master. Once communications with the
+ master is initiated, the I2C_clear_smsbus_alert() function is used to clear
+ the alert condition.
+
+ The I2C_enable_smbus_irq() and I2C_disable_smbus_irq() functions are used to
+ enable and disable the SMBSUS and SMBALERT SMBus interrupts.
+
+ *//*=========================================================================*/
+
+#ifndef CORE_I2C_H_
+#define CORE_I2C_H_
+
+#include "cpu_types.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_RELEASE_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must be generated at the end of the I2C transaction to release
+ the bus.
+ */
+#define I2C_RELEASE_BUS 0x00u
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_HOLD_BUS constant is used to specify the options parameter to
+ functions I2C_read(), I2C_write() and I2C_write_read() to indicate
+ that a STOP bit must not be generated at the end of the I2C transaction in
+ order to retain the bus ownership. This causes the next transaction to
+ begin with a repeated START bit and no STOP bit between the transactions.
+ */
+#define I2C_HOLD_BUS 0x01u
+
+/*-------------------------------------------------------------------------*//**
+ The following constants specify the interrupt identifier number which will be
+ solely used by driver API. This has nothing to do with hardware interrupt line.
+ I2C_INT_IRQ is the primary interrupt signal which drives the state machine
+ of the CoreI2C driver. The I2C_SMBALERT_IRQ and I2C_SMBUS_IRQ are used by
+ SMBus interrupt enable and disable functions. These IRQ numbers are also used
+ by I2C_get_irq_status().
+ */
+#define I2C_NO_IRQ 0x00u
+#define I2C_SMBALERT_IRQ 0x01u
+#define I2C_SMBSUS_IRQ 0x02u
+#define I2C_INTR_IRQ 0x04u
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_NO_TIMEOUT constant is used as parameter to the I2C_wait_complete()
+ function to indicate that the wait for completion of the transaction should
+ not time out.
+ */
+#define I2C_NO_TIMEOUT 0u
+
+/*-------------------------------------------------------------------------*//**
+ The i2c_channel_number_t type is used to specify the channel number of a
+ CoreI2C instance.
+ */
+typedef enum i2c_channel_number {
+ I2C_CHANNEL_0 = 0u,
+ I2C_CHANNEL_1,
+ I2C_CHANNEL_2,
+ I2C_CHANNEL_3,
+ I2C_CHANNEL_4,
+ I2C_CHANNEL_5,
+ I2C_CHANNEL_6,
+ I2C_CHANNEL_7,
+ I2C_CHANNEL_8,
+ I2C_CHANNEL_9,
+ I2C_CHANNEL_10,
+ I2C_CHANNEL_11,
+ I2C_CHANNEL_12,
+ I2C_CHANNEL_13,
+ I2C_CHANNEL_14,
+ I2C_CHANNEL_15,
+ I2C_MAX_CHANNELS = 16u
+} i2c_channel_number_t;
+
+/*-------------------------------------------------------------------------*//**
+ The i2c_clock_divider_t type is used to specify the divider to be applied
+ to the I2C PCLK or BCLK signal in order to generate the I2C clock.
+ The I2C_BCLK_DIV_8 value selects a clock frequency based on division of BCLK,
+ all other values select a clock frequency based on division of PCLK.
+ */
+typedef enum i2c_clock_divider {
+ I2C_PCLK_DIV_256 = 0u,
+ I2C_PCLK_DIV_224,
+ I2C_PCLK_DIV_192,
+ I2C_PCLK_DIV_160,
+ I2C_PCLK_DIV_960,
+ I2C_PCLK_DIV_120,
+ I2C_PCLK_DIV_60,
+ I2C_BCLK_DIV_8
+} i2c_clock_divider_t;
+
+/*-------------------------------------------------------------------------*//**
+ The i2c_status_t type is used to report the status of I2C transactions.
+ */
+typedef enum i2c_status
+{
+ I2C_SUCCESS = 0u,
+ I2C_IN_PROGRESS,
+ I2C_FAILED,
+ I2C_TIMED_OUT
+} i2c_status_t;
+
+/*-------------------------------------------------------------------------*//**
+ The i2c_slave_handler_ret_t type is used by slave write handler functions
+ to indicate whether or not the received data buffer should be released.
+ */
+typedef enum i2c_slave_handler_ret {
+ I2C_REENABLE_SLAVE_RX = 0u,
+ I2C_PAUSE_SLAVE_RX = 1u
+} i2c_slave_handler_ret_t;
+
+typedef struct i2c_instance i2c_instance_t ;
+
+/*-------------------------------------------------------------------------*//**
+ Slave write handler functions prototype.
+ ------------------------------------------------------------------------------
+ This defines the function prototype that must be followed by I2C slave write
+ handler functions. These functions are registered with the CoreI2C driver
+ through the I2C_register_write_handler() function.
+
+ Declaring and Implementing Slave Write Handler Functions:
+ Slave write handler functions should follow the following prototype:
+ i2c_slave_handler_ret_t write_handler
+ (
+ i2c_instance_t *instance, uint8_t * data, uint16_t size
+ );
+
+ The instance parameter is a pointer to the i2c_instance_t for which this
+ slave write handler has been declared.
+
+ The data parameter is a pointer to a buffer (received data buffer) holding
+ the data written to the I2C slave.
+
+ Defining the macro INCLUDE_SLA_IN_RX_PAYLOAD causes the driver to insert the
+ actual address used to access the slave as the first byte in the buffer.
+ This allows applications tailor their response based on the actual address
+ used to access the slave (primary address, secondary address or GCA).
+
+ The size parameter is the number of bytes held in the received data buffer.
+ Handler functions must return one of the following values:
+ I2C_REENABLE_SLAVE_RX
+ I2C_PAUSE_SLAVE_RX.
+
+ If the handler function returns I2C_REENABLE_SLAVE_RX, the driver releases
+ the received data buffer and allows further I2C write transactions to the
+ I2C slave to take place.
+
+ If the handler function returns I2C_PAUSE_SLAVE_RX, the I2C slave responds
+ to subsequent write requests with a non-acknowledge bit (NACK), until the
+ received data buffer content has been processed by some other part of the
+ software application.
+
+ A call to I2C_enable_slave() is required at some point after returning
+ I2C_PAUSE_SLAVE_RX in order to release the received data buffer so it can
+ be used to store data received by subsequent I2C write transactions.
+ */
+typedef i2c_slave_handler_ret_t (*i2c_slave_wr_handler_t)(i2c_instance_t *instance, uint8_t *, uint16_t );
+
+
+/*-------------------------------------------------------------------------*//**
+ i2c_instance_t
+ ------------------------------------------------------------------------------
+ This structure is used to identify the various CoreI2C hardware instances in
+ your system and the I2C channels within them. Your application software should
+ declare one instance of this structure for each channel of each instance of
+ CoreI2C in your system. The functions I2C_init() and I2C_channel_init()
+ initialize this structure depending on whether it is channel 0 or one of the
+ additional channels respectively. A pointer to an initialized instance of the
+ structure should be passed as the first parameter to the CoreI2C driver
+ functions, to identify which CoreI2C hardware instance and channel should
+ perform the requested operation.
+
+ The contents of this data structure should not be modified or used outside of
+ the CoreI2C driver. Software using the CoreI2C driver should only need to
+ create one single instance of this data structure for each channel of each
+ CoreI2C hardware instance in the system then pass a pointer to these data
+ structures with each call to the CoreI2C driver in order to identify the
+ CoreI2C hardware instance it wishes to use.
+ */
+struct i2c_instance
+{
+ addr_t base_address;
+ uint_fast8_t ser_address;
+
+ /* Transmit related info:*/
+ uint_fast8_t target_addr;
+
+ /* Current transaction type (WRITE, READ, RANDOM_READ)*/
+ uint8_t transaction;
+
+ uint_fast16_t random_read_addr;
+
+ uint8_t options;
+
+ /* Master TX INFO: */
+ const uint8_t * master_tx_buffer;
+ uint_fast16_t master_tx_size;
+ uint_fast16_t master_tx_idx;
+ uint_fast8_t dir;
+
+ /* Master RX INFO: */
+ uint8_t * master_rx_buffer;
+ uint_fast16_t master_rx_size;
+ uint_fast16_t master_rx_idx;
+
+ /* Master Status */
+ volatile i2c_status_t master_status;
+ uint32_t master_timeout_ms;
+
+ /* Slave TX INFO */
+ const uint8_t * slave_tx_buffer;
+ uint_fast16_t slave_tx_size;
+ uint_fast16_t slave_tx_idx;
+
+ /* Slave RX INFO */
+ uint8_t * slave_rx_buffer;
+ uint_fast16_t slave_rx_size;
+ uint_fast16_t slave_rx_idx;
+ /* Slave Status */
+ volatile i2c_status_t slave_status;
+
+ /* Slave data: */
+ uint_fast8_t slave_mem_offset_length;
+ i2c_slave_wr_handler_t slave_write_handler;
+ uint8_t is_slave_enabled;
+
+ /* user specific data */
+ void *p_user_data ;
+
+ /* I2C bus status */
+ uint8_t bus_status;
+
+ /* Is transaction pending flag */
+ uint8_t is_transaction_pending;
+
+ /* I2C Pending transaction */
+ uint8_t pending_transaction;
+};
+
+/*-------------------------------------------------------------------------*//**
+ I2C initialization routine.
+ ------------------------------------------------------------------------------
+ The I2C_init() function is used to configure channel 0 of a CoreI2C instance.
+ It sets the base hardware address which is used to locate the CoreI2C instance
+ in memory and also used internally by I2C_channel_init() to calculate the
+ register addresses for any additional channels. The slave serial address set
+ is shared by all channels on a CoreI2C instance.
+
+ If only one channel is configured in a CoreI2C, the address of the
+ i2c_instance_t used in I2C_Init() will also be used in subsequent calls to the
+ CoreI2C driver functions. If more than one channel is configured in the
+ CoreI2C, I2C_channel_init() will be called after I2C_init(), which initializes
+ the i2c_instance_t data structure for a specific channel.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ Pointer to the i2c_instance_t data structure which will hold all data
+ related to channel 0 of the CoreI2C instance being initialized. A pointer
+ to this structure will be used in all subsequent calls to CoreI2C driver
+ functions which are to operate on channel 0 of this CoreI2C instance.
+
+ @param base_address:
+ Base address in the processor's memory map of the registers of the CoreI2C
+ instance being initialized.
+
+ @param ser_address:
+ This parameter sets the primary I2C serial address (SLAVE0 address) for the
+ CoreI2C being initialized. It is the principal I2C bus address to which the
+ CoreI2C instance will respond. CoreI2C can operate in master mode or slave
+ mode and the serial address is significant only in the case of I2C slave
+ mode. In master mode, CoreI2C does not require a serial address and the
+ value of this parameter is not important. If you do not intend to use the
+ CoreI2C device in slave mode, then any dummy slave address value can be
+ provided to this parameter. However, in systems where the CoreI2C may be
+ expected to switch from master mode to slave mode, it is advisable to
+ initialize the CoreI2C device with a valid serial slave address.
+
+ You need to call the I2C_init() function whenever it is required to change
+ the primary slave address as there is no separate function to set the
+ primary slave address of the I2C device. The serial address being
+ initialized through this function is basically the primary slave address or
+ slave address0. I2C_set_slave_second_addr() can be used to set the
+ secondary slave address or slave address 1.
+ Note : ser_address parameter does not have any affect if fixed slave
+ address is enabled in CoreI2C hardware design. CoreI2C will
+ be always addressed with the hardware configured fixed slave
+ address.
+ Note : ser_address parameter will not have any affect if the CoreI2C
+ instance is only used in master mode.
+
+ @param ser_clock_speed:
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that will be used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ I2C_PCLK_DIV_256
+ I2C_PCLK_DIV_224
+ I2C_PCLK_DIV_192
+ I2C_PCLK_DIV_160
+ I2C_PCLK_DIV_960
+ I2C_PCLK_DIV_120
+ I2C_PCLK_DIV_60
+ I2C_BCLK_DIV_8
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is
+ enabled in CoreI2C hardware instance configuration dialogue window.
+ The fixed baud rate divider value will override the value
+ passed as parameter in this function.
+ Note: serial_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ }
+ @endcode
+ */
+void I2C_init
+(
+ i2c_instance_t * this_i2c,
+ addr_t base_address,
+ uint8_t ser_address,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C channel initialization routine.
+ ------------------------------------------------------------------------------
+ The I2C_channel_init() function initializes and configures hardware and data
+ structures of one of the additional channels of a CoreI2C instance.
+ I2C_init() must be called before calling this function to set the CoreI2C
+ instance hardware base address and I2C serial address. I2C_channel_init() also
+ initializes I2C serial clock divider to set the serial clock baud rate.
+ The pointer to data structure i2c_instance_t used for a particular channel
+ will be used as an input parameter to subsequent CoreI2C driver functions
+ which operate on this channel.
+ ------------------------------------------------------------------------------
+ @param this_i2c_channel
+ Pointer to the i2c_instance_t data structure holding all data related to the
+ CoreI2C channel being initialized. A pointer to the same data structure will
+ be used in subsequent calls to the CoreI2C driver functions in order to
+ identify the CoreI2C channel instance that should perform the operation
+ implemented by the called driver function.
+
+ @param this_i2c:
+ This is a pointer to an i2c_instance_t structure previously initialized by
+ I2C_init(). It holds information regarding the hardware base address and
+ I2C serial address for the CoreI2C containing the channel to be
+ initialized. This information is required by I2C_channel_init() to
+ initialize the i2c_instance_t structure pointed to by this_i2c_channel as
+ all channels in a CoreI2C instance share the same base address and serial
+ address. It is very important that the i2c_instance_t structure pointed to
+ by this_i2c has been previously initialized with a call to I2C_init().
+
+ @param channel_number:
+ This parameter of type i2c_channel_number_t identifies the channel to be
+ initialized.
+
+ @param ser_clock_speed:
+ This parameter sets the I2C serial clock frequency. It selects the divider
+ that will be used to generate the serial clock from the APB PCLK or from
+ the BCLK. It can be one of the following:
+ I2C_PCLK_DIV_256
+ I2C_PCLK_DIV_224
+ I2C_PCLK_DIV_192
+ I2C_PCLK_DIV_160
+ I2C_PCLK_DIV_960
+ I2C_PCLK_DIV_120
+ I2C_PCLK_DIV_60
+ I2C_BCLK_DIV_8
+
+ Note: serial_clock_speed value will have no affect if Fixed baud rate is
+ enabled in CoreI2C hardware instance configuration dialogue window.
+ The fixed baud rate divider value will supersede the value
+ passed as parameter in this function.
+
+ Note: ser_clock_speed value is not critical for devices that only operate
+ as slaves and can be set to any of the above values.
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+ i2c_instance_t g_i2c_channel_1_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void system_init( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize CoreI2C channel 1 with different clock speed
+ I2C_channel_init( &g_i2c_channel_1_inst, &g_i2c_inst, I2C_CHANNEL_1,
+ I2C_PCLK_DIV_224 );
+
+ // Write data to Channel 1 of CoreI2C instance.
+ I2C_write( &g_i2c_channel_1_inst, target_slave_addr, tx_buffer,
+ write_length, I2C_RELEASE_BUS );
+ }
+ @endcode
+
+*/
+void I2C_channel_init
+(
+ i2c_instance_t * this_i2c_channel,
+ i2c_instance_t * this_i2c,
+ i2c_channel_number_t channel_number,
+ i2c_clock_divider_t ser_clock_speed
+);
+
+/*------------------------------------------------------------------------------
+ CoreI2C interrupt service routine.
+ ------------------------------------------------------------------------------
+ The function I2C_isr is the CoreI2C interrupt service routine. User must
+ call this function from their application level CoreI2C interrupt handler
+ function. This function runs the I2C state machine based on previous and
+ current status.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return none
+
+ Example:
+ @code
+
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREINTERRUPT_BASE_ADDR 0xCC000000u
+ #define COREI2C_SER_ADDR 0x10u
+ #define I2C_IRQ_NB 2u
+
+ i2c_instance_t g_i2c_inst;
+
+ void core_i2c_isr( void )
+ {
+ I2C_isr( &g_i2c_inst );
+ }
+
+ void main( void )
+ {
+ CIC_init( COREINTERRUPT_BASE_ADDR );
+ NVIC_init();
+ CIC_set_irq_handler( I2C_IRQ_NB, core_i2c_isr );
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ NVIC_enable_interrupt( NVIC_IRQ_0 );
+ }
+ @endcode
+ */
+void I2C_isr
+(
+ i2c_instance_t * this_i2c
+);
+
+/*******************************************************************************
+ *******************************************************************************
+ *
+ * Master specific functions
+ *
+ * The following functions are only used within an I2C master's implementation.
+ */
+
+/*-------------------------------------------------------------------------*//**
+ I2C master write function.
+ ------------------------------------------------------------------------------
+ This function initiates an I2C master write transaction. This function returns
+ immediately after initiating the transaction. The content of the write buffer
+ passed as parameter should not be modified until the write transaction
+ completes. It also means that the memory allocated for the write buffer should
+ not be freed or should not go out of scope before the write completes. You can
+ check for the write transaction completion using the I2C_status() function.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr:
+ This parameter specifies the serial address of the target I2C device.
+
+ @param write_buffer:
+ This parameter is a pointer to a buffer holding the data to be written to
+ the target I2C device.
+ Care must be taken not to release the memory used by this buffer before the
+ write transaction completes. For example, it is not appropriate to return
+ from a function allocating this buffer as an auto array variable before the
+ write transaction completes as this would result in the buffer's memory
+ being de-allocated from the stack when the function returns. This memory
+ could then be subsequently reused and modified causing unexpected data to
+ be written to the target I2C device.
+
+ @param write_size:
+ Number of bytes held in the write_buffer to be written to the target I2C
+ device.
+
+ @param options:
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t tx_buffer[DATA_LENGTH];
+ uint8_t write_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Write data to Channel 0 of CoreI2C instance.
+ I2C_write( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * write_buffer,
+ uint16_t write_size,
+ uint8_t options
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C master read.
+ ------------------------------------------------------------------------------
+ This function initiates an I2C master read transaction. This function returns
+ immediately after initiating the transaction.
+ The contents of the read buffer passed as parameter should not be modified
+ until the read transaction completes. It also means that the memory allocated
+ for the read buffer should not be freed or should not go out of scope before
+ the read completes. You can check for the read transaction completion using
+ the I2C_status() function.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr:
+ This parameter specifies the serial address of the target I2C device.
+
+ @param read_buffer
+ This is a pointer to a buffer where the data received from the target device
+ will be stored.
+ Care must be taken not to release the memory used by this buffer before the
+ read transaction completes. For example, it is not appropriate to return
+ from a function allocating this buffer as an auto array variable before the
+ read transaction completes as this would result in the buffer's memory being
+ de-allocated from the stack when the function returns. This memory could
+ then be subsequently reallocated resulting in the read transaction
+ corrupting the newly allocated memory.
+
+ @param read_size:
+ This parameter specifies the number of bytes to read from the target device.
+ This size must not exceed the size of the read_buffer buffer.
+
+ @param options:
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the read transaction causing the bus to be released for other I2C
+ devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the read transaction,
+ preventing other I2C devices from initiating a bus transaction.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from target slave Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C master write-read
+ ------------------------------------------------------------------------------
+ This function initiates an I2C write-read transaction where data is first
+ written to the target device before issuing a restart condition and changing
+ the direction of the I2C transaction in order to read from the target device.
+
+ The same warnings about buffer allocation in I2C_write() and I2C_read()
+ apply to this function.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param serial_addr:
+ This parameter specifies the serial address of the target I2C device.
+
+ @param addr_offset:
+ This parameter is a pointer to the buffer containing the data that will be
+ sent to the slave during the write phase of the write-read transaction. This
+ data is typically used to specify an address offset specifying to the I2C
+ slave device what data it must return during the read phase of the
+ write-read transaction.
+
+ @param offset_size:
+ This parameter specifies the number of offset bytes to be written during the
+ write phase of the write-read transaction. This is typically the size of the
+ buffer pointed to by the addr_offset parameter.
+
+ @param read_buffer:
+ This parameter is a pointer to the buffer where the data read from the I2C
+ slave will be stored.
+
+ @param read_size:
+ This parameter specifies the number of bytes to read from the target I2C
+ slave device. This size must not exceed the size of the buffer pointed to by
+ the read_buffer parameter.
+
+ @param options:
+ The options parameter is used to indicate if the I2C bus should be released
+ on completion of the write-read transaction. Using the I2C_RELEASE_BUS
+ constant for the options parameter causes a STOP bit to be generated at the
+ end of the write-read transaction causing the bus to be released for other
+ I2C devices to use. Using the I2C_HOLD_BUS constant as options parameter
+ prevents a STOP bit from being generated at the end of the write-read
+ transaction, preventing other I2C devices from initiating a bus transaction.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define TX_LENGTH 16u
+ #define RX_LENGTH 8u
+
+ i2c_instance_t g_i2c_inst;
+ uint8_t rx_buffer[RX_LENGTH];
+ uint8_t read_length = RX_LENGTH;
+ uint8_t tx_buffer[TX_LENGTH];
+ uint8_t write_length = TX_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ I2C_write_read( &g_i2c_inst, target_slave_addr, tx_buffer, write_length,
+ rx_buffer, read_length, I2C_RELEASE_BUS );
+
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+void I2C_write_read
+(
+ i2c_instance_t * this_i2c,
+ uint8_t serial_addr,
+ const uint8_t * addr_offset,
+ uint16_t offset_size,
+ uint8_t * read_buffer,
+ uint16_t read_size,
+ uint8_t options
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C status
+ ------------------------------------------------------------------------------
+ This function indicates the current state of a CoreI2C channel.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ ------------------------------------------------------------------------------
+ @return
+ The return value indicates the current state of a CoreI2C channel or the
+ outcome of the previous transaction if no transaction is in progress.
+ Possible return values are:
+ I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ I2C_IN_PROGRESS
+ There is an I2C transaction in progress.
+ I2C_FAILED
+ The last I2C transaction failed.
+ I2C_TIMED_OUT
+ The request has failed to complete in the allotted time.
+
+ Example:
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ while( I2C_IN_PROGRESS == I2C_get_status( &g_i2c_inst ) )
+ {
+ // Do something useful while waiting for I2C operation to complete
+ our_i2c_busy_task();
+ }
+
+ if( I2C_SUCCESS != I2C_get_status( &g_i2c_inst ) )
+ {
+ // Something went wrong...
+ our_i2c_error_recovery( &g_i2c_inst );
+ }
+ @endcode
+ */
+i2c_status_t I2C_get_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ Wait for I2C transaction completion.
+ ------------------------------------------------------------------------------
+ This function waits for the current I2C transaction to complete. The return
+ value indicates whether the last I2C transaction was successful or not.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param timeout_ms:
+ The timeout_ms parameter specified the delay within which the current I2C
+ transaction is expected to complete. The time out delay is given in
+ milliseconds. I2C_wait_complete() will return I2C_TIMED_OUT if the current
+ transaction has not completed after the time out delay has expired. This
+ parameter can be set to I2C_NO_TIMEOUT to indicate that I2C_wait_complete()
+ must not time out.
+ ------------------------------------------------------------------------------
+ @return
+ The return value indicates the outcome of the last I2C transaction. It can
+ be one of the following:
+ I2C_SUCCESS
+ The last I2C transaction has completed successfully.
+ I2C_FAILED
+ The last I2C transaction failed.
+ I2C_TIMED_OUT
+ The last transaction failed to complete within the time out delay given
+ as second parameter.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define COREI2C_DUMMY_ADDR 0x10u
+ #define DATA_LENGTH 16u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t rx_buffer[DATA_LENGTH];
+ uint8_t read_length = DATA_LENGTH;
+
+ void main( void )
+ {
+ uint8_t target_slave_addr = 0x12;
+ i2c_status_t status;
+
+ // Initialize base CoreI2C instance
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, COREI2C_DUMMY_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Read data from Channel 0 of CoreI2C instance.
+ I2C_read( &g_i2c_inst, target_slave_addr, rx_buffer, read_length,
+ I2C_RELEASE_BUS );
+
+ // Wait for completion and record the outcome
+ status = I2C_wait_complete( &g_i2c_inst, I2C_NO_TIMEOUT );
+ }
+ @endcode
+ */
+i2c_status_t I2C_wait_complete
+(
+ i2c_instance_t * this_i2c,
+ uint32_t timeout_ms
+);
+
+/*-------------------------------------------------------------------------*//**
+ Time out delay expiration.
+ ------------------------------------------------------------------------------
+ This function is used to control the expiration of the time out delay
+ specified as a parameter to the I2C_wait_complete() function. It must be
+ called from the interrupt service routine of a periodic interrupt source such
+ as the Cortex-M3 SysTick timer interrupt. It takes the period of the interrupt
+ source as its ms_since_last_tick parameter and uses it as the time base for
+ the I2C_wait_complete() function’s time out delay.
+
+ Note: This function does not need to be called if the I2C_wait_complete()
+ function is called with a timeout_ms value of I2C_NO_TIMEOUT.
+ Note: If this function is not called then the I2C_wait_complete() function
+ will behave as if its timeout_ms was specified as I2C_NO_TIMEOUT and it
+ will not time out.
+ Note: If this function is being called from an interrupt handler (e.g SysTick)
+ it is important that the calling interrupt have a lower priority than
+ the CoreI2C interrupt(s) to ensure any updates to shared data are
+ protected.
+
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+ @param ms_since_last_tick:
+ The ms_since_last_tick parameter specifies the number of milliseconds that
+ elapsed since the last call to I2C_system_tick(). This parameter would
+ typically be a constant specifying the interrupt rate of a timer used to
+ generate system ticks.
+ ------------------------------------------------------------------------------
+ @return
+ none.
+
+ Example:
+ The example below shows an example of how the I2C_system_tick() function
+ would be called in a Cortex-M3 based system. I2C_system_tick() is called for
+ each I2C channel from the Cortex-M3 SysTick timer interrupt service routine.
+ The SysTick is configured to generate an interrupt every 10 milliseconds in
+ the example below.
+ @code
+ #define SYSTICK_INTERVAL_MS 10
+
+ void SysTick_Handler(void)
+ {
+ I2C_system_tick(&g_core_i2c0, SYSTICK_INTERVAL_MS);
+ I2C_system_tick(&g_core_i2c2, SYSTICK_INTERVAL_MS);
+ }
+ @endcode
+ */
+void I2C_system_tick
+(
+ i2c_instance_t * this_i2c,
+ uint32_t ms_since_last_tick
+);
+
+/*******************************************************************************
+ *******************************************************************************
+ *
+ * Slave specific functions
+ *
+ * The following functions are only used within the implementation of an I2C
+ * slave device.
+ */
+
+/*-------------------------------------------------------------------------*//**
+ I2C slave transmit buffer configuration.
+ ------------------------------------------------------------------------------
+ This function specifies the memory buffer holding the data that will be sent
+ to the I2C master when this CoreI2C channel is the target of an I2C read or
+ write-read transaction.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param tx_buffer:
+ This parameter is a pointer to the memory buffer holding the data to be
+ returned to the I2C master when this CoreI2C channel is the target of an
+ I2C read or write-read transaction.
+
+ @param tx_size:
+ Size of the transmit buffer pointed to by the tx_buffer parameter.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the transmit buffer containing the data that will be
+ // returned to the master during read and write-read transactions.
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_tx_buffer
+(
+ i2c_instance_t * this_i2c,
+ const uint8_t * tx_buffer,
+ uint16_t tx_size
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C slave receive buffer configuration.
+ ------------------------------------------------------------------------------
+ This function specifies the memory buffer that will be used by the CoreI2C
+ channel to receive data when it is a slave. This buffer is the memory where
+ data will be stored when the CoreI2C channel is the target of an I2C master
+ write transaction (i.e. when it is the slave).
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param rx_buffer:
+ This parameter is a pointer to the memory buffer allocated by the caller
+ software to be used as a slave receive buffer.
+
+ @param rx_size:
+ Size of the slave receive buffer. This is the amount of memory that is
+ allocated to the buffer pointed to by rx_buffer.
+ Note: This buffer size indirectly specifies the maximum I2C write
+ transaction length this CoreI2C channel can be the target of. This
+ is because this CoreI2C channel responds to further received
+ bytes with a non-acknowledge bit (NACK) as soon as its receive
+ buffer is full. This causes the write transaction to fail.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_RX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_rx_buffer[SLAVE_RX_BUFFER_SIZE];
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Specify the buffer used to store the data written by the I2C master.
+ I2C_set_slave_rx_buffer( &g_i2c_inst, g_slave_rx_buffer,
+ sizeof(g_slave_rx_buffer) );
+ }
+ @endcode
+ */
+void I2C_set_slave_rx_buffer
+(
+ i2c_instance_t * this_i2c,
+ uint8_t * rx_buffer,
+ uint16_t rx_size
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C slave memory offset length configuration.
+ ------------------------------------------------------------------------------
+ This function is used as part of the configuration of a CoreI2C channel for
+ operation as a slave supporting write-read transactions. It specifies the
+ number of bytes expected as part of the write phase of a write-read
+ transaction. The bytes received during the write phase of a write-read
+ transaction will be interpreted as an offset into the slave's transmit buffer.
+ This allows random access into the I2C slave transmit buffer from a remote
+ I2C master.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param offset_length:
+ The offset_length parameter configures the number of bytes to be interpreted
+ by the CoreI2C slave as a memory offset value during the write phase of
+ write-read transactions. The maximum value for the offset_length parameter
+ is two. The value of offset_length has the following effect on the
+ interpretation of the received data.
+
+ If offset_length is 0, the offset into the transmit buffer is fixed at 0.
+
+ If offset_length is 1, a single byte of received data is interpreted as an
+ unsigned 8 bit offset value in the range 0 to 255.
+
+ If offset_length is 2, 2 bytes of received data are interpreted as an
+ unsigned 16 bit offset value in the range 0 to 65535. The first byte
+ received in this case provides the high order bits of the offset and
+ the second byte provides the low order bits.
+
+ If the number of bytes received does not match the non 0 value of
+ offset_length the transmit buffer offset is set to 0.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ }
+ @endcode
+ */
+void I2C_set_slave_mem_offset_length
+(
+ i2c_instance_t * this_i2c,
+ uint8_t offset_length
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C write handler registration.
+ ------------------------------------------------------------------------------
+ Register the function that is called to process the data written to this
+ CoreI2C channel when it is the slave in an I2C write transaction.
+ Note: If a write handler is registered, it is called on completion of the
+ write phase of a write-read transaction and responsible for processing
+ the received data in the slave receive buffer and populating the slave
+ transmit buffer with the data that will be transmitted to the I2C master
+ as part of the read phase of the write-read transaction. If a write
+ handler is not registered, the write data of a write read transaction is
+ interpreted as an offset into the slave’s transmit buffer and handled by
+ the driver.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param handler:
+ Pointer to the function that will process the I2C write request.
+
+ @return none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SLAVE_TX_BUFFER_SIZE 10u
+
+ i2c_instance_t g_i2c_inst;
+
+ uint8_t g_slave_tx_buffer[SLAVE_TX_BUFFER_SIZE] = { 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10 };
+
+ // local function prototype
+ void slave_write_handler
+ (
+ i2c_instance_t * this_i2c,
+ uint8_t * p_rx_data,
+ uint16_t rx_size
+ );
+
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, I2C serial
+ // address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_tx_buffer( &g_i2c_inst, g_slave_tx_buffer,
+ sizeof(g_slave_tx_buffer) );
+ I2C_set_slave_mem_offset_length( &g_i2c_inst, 1 );
+ I2C_register_write_handler( &g_i2c_inst, slave_write_handler );
+ }
+ @endcode
+*/
+void I2C_register_write_handler
+(
+ i2c_instance_t * this_i2c,
+ i2c_slave_wr_handler_t handler
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C slave enable.
+ ------------------------------------------------------------------------------
+ This function enables slave mode operation for a CoreI2C channel. It enables
+ the CoreI2C slave to receive data when it is the target of an I2C read, write
+ or write-read transaction.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return none.
+
+ Example:
+ @code
+ // Enable I2C slave
+ I2C_enable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_enable_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ I2C slave disable.
+ ------------------------------------------------------------------------------
+ This function disables slave mode operation for a CoreI2C channel. It stops
+ the CoreI2C slave acknowledging I2C read, write or write-read transactions
+ targeted at it.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return none.
+
+ Example:
+ @code
+ // Disable I2C slave
+ I2C_disable_slave( &g_i2c_inst );
+ @endcode
+ */
+void I2C_disable_slave
+(
+ i2c_instance_t * this_i2c
+);
+/*-------------------------------------------------------------------------*//**
+ Set I2C slave second address.
+ ------------------------------------------------------------------------------
+ The function I2C_set_slave_second_addr() sets the secondary slave address for
+ a CoreI2C slave device. This is an additional slave address which might be
+ required in certain applications, for example to enable fail-safe operation in
+ a system. As the CoreI2C device supports 7-bit addressing, the highest value
+ which can be assigned to second slave address is 127 (0x7F).
+ Note: This function does not support CoreI2C hardware configured with a fixed
+ second slave address. The current implementation of the ADDR1[0] register
+ bit makes it difficult for the driver to support both programmable and
+ fixed second slave address, so we choose to support programmable only.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param second_slave_addr:
+ The second_slave_addr parameter is the secondary slave address of the I2C
+ device.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+ #define SECOND_SLAVE_ADDR 0x20u
+
+ i2c_instance_t g_i2c_inst;
+ void main( void )
+ {
+ // Initialize the CoreI2C driver with its base address, primary I2C
+ // serial address and serial clock divider.
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+ I2C_set_slave_second_addr( &g_i2c_inst, SECOND_SLAVE_ADDR );
+ }
+ @endcode
+ */
+void I2C_set_slave_second_addr
+(
+ i2c_instance_t * this_i2c,
+ uint8_t second_slave_addr
+);
+
+/*-------------------------------------------------------------------------*//**
+ Disable second slave address.
+ ------------------------------------------------------------------------------
+ The function I2C_disable_slave_second_addr() disables the secondary slave
+ address of the CoreI2C slave device.
+ Note: This version of the driver only supports CoreI2C hardware configured
+ with a programmable second slave address.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ i2c_instance_t g_i2c_inst;
+ I2C_disable_slave_second_addr( &g_i2c_inst);
+ @endcode
+ */
+void I2C_disable_slave_second_addr
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_set_gca() function is used to set the general call acknowledgement bit
+ of a CoreI2C slave device. This allows all channels of the CoreI2C slave
+ device respond to a general call or broadcast message from an I2C master.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Enable recognition of the General Call Address
+ I2C_set_gca( &g_i2c_inst );
+ @endcode
+ */
+void I2C_set_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_clear_gca() function is used to clear the general call acknowledgement
+ bit of a CoreI2C slave device. This will stop all channels of the I2C slave
+ device responding to any general call or broadcast message from the master.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ i2c_instance_t g_i2c_inst;
+
+ // Disable recognition of the General Call Address
+ I2C_clear_gca( &g_i2c_inst );
+ @endcode
+ */
+
+void I2C_clear_gca
+(
+ i2c_instance_t * this_i2c
+);
+
+/*------------------------------------------------------------------------------
+ I2C SMBUS specific APIs
+ ----------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_smbus_init() function enables SMBus timeouts and status logic for a
+ CoreI2C channel.
+ Note: This and any of the other SMBus related functionality will only have an
+ effect if the CoreI2C was instantiated with the Generate SMBus Logic
+ option checked.
+ Note: If the CoreI2C was instantiated with the Generate IPMI Logic option
+ checked this function will enable the IPMI 3mS SCL low timeout but none
+ of the other SMBus functions will have any effect.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void system_init( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst);
+ }
+ @endcode
+ */
+void I2C_smbus_init
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_enable_smbus_irq() function is used to enable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specify the SMBUS interrupt(s) which will be enabled.
+ The two possible interrupts are:
+ I2C_SMBALERT_IRQ
+ I2C_SMBSUS_IRQ
+ To enable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ none
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ) );
+ }
+ @endcode
+ */
+void I2C_enable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_disable_smbus_irq() function is used to disable the CoreI2C channel’s
+ SMBSUS and SMBALERT SMBus interrupts.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param irq_type
+ The irq_type specifies the SMBUS interrupt(s) which will be disabled.
+ The two possible interrupts are:
+ I2C_SMBALERT_IRQ
+ I2C_SMBSUS_IRQ
+ To disable both ints in one call, use I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both SMBALERT & SMBSUS interrupts
+ I2C_enable_smbus_irq( &g_i2c_inst,
+ (uint8_t)(I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ));
+
+ ...
+
+ // Disable the SMBALERT interrupt
+ I2C_disable_smbus_irq( &g_i2c_inst, I2C_SMBALERT_IRQ );
+ }
+ @endcode
+ */
+void I2C_disable_smbus_irq
+(
+ i2c_instance_t * this_i2c,
+ uint8_t irq_type
+);
+
+/*-------------------------------------------------------------------------*//**
+ The function I2C_suspend_smbus_slave() forces any SMBUS slave devices
+ connected to a CoreI2C channel into power down or suspend mode by asserting
+ the channel's SMBSUS signal. The CoreI2C channel is the SMBus master in this
+ case.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_suspend_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The function I2C_resume_smbus_slave() de-asserts the CoreI2C channel's SMBSUS
+ signal to take any connected slave devices out of suspend mode. The CoreI2C
+ channel is the SMBus master in this case.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // suspend SMBus slaves
+ I2C_suspend_smbus_slave( &g_i2c_inst );
+
+ ...
+
+ // Re-enable SMBus slaves
+ I2C_resume_smbus_slave( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_resume_smbus_slave
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_reset_smbus() function resets the CoreI2C channel's SMBus connection
+ by forcing SCLK low for 35mS. The reset is automatically cleared after 35ms
+ have elapsed. The CoreI2C channel is the SMBus master in this case.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Make sure the SMBus channel is in a known state by resetting it
+ I2C_reset_smbus( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_reset_smbus
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_set_smbus_alert() function is used to force master communication with
+ an I2C slave device by asserting the CoreI2C channel’s SMBALERT signal. The
+ CoreI2C channel is the SMBus slave in this case.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_set_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_clear_smbus_alert() function is used de-assert the CoreI2C channel’s
+ SMBALERT signal once a slave device has had a response from the master. The
+ CoreI2C channel is the SMBus slave in this case.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ none.
+
+ Example:
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Get the SMBus masters attention
+ I2C_set_smbus_alert( &g_i2c_inst );
+
+ ...
+
+ // Once we are happy, drop the alert
+ I2C_clear_smbus_alert( &g_i2c_inst );
+ }
+ @endcode
+ */
+void I2C_clear_smbus_alert
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_get_irq_status function returns information on which interrupts are
+ currently pending in a CoreI2C channel.
+ The interrupts supported by CoreI2C are:
+ * SMBUSALERT
+ * SMBSUS
+ * INTR
+ The macros I2C_NO_IRQ, I2C_SMBALERT_IRQ, I2C_SMBSUS_IRQ and I2C_INTR_IRQ are
+ provided for use with this function.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns the status of the CoreI2C channel’s interrupts as a
+ single byte bitmap where a bit is set to indicate a pending interrupt.
+ The following are the bit positions associated with each interrupt type:
+ Bit 0 - SMBUS_ALERT_IRQ
+ Bit 1 - SMBSUS_IRQ
+ Bit 2 - INTR_IRQ
+ It returns 0, if there are no pending interrupts.
+
+ Example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+
+ void main( void )
+ {
+ uint8_t irq_to_enable = I2C_SMBALERT_IRQ | I2C_SMBSUS_IRQ;
+ uint8_t pending_irq = 0u;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Initialize SMBus feature
+ I2C_smbus_init( &g_i2c_inst );
+
+ // Enable both I2C_SMBALERT_IRQ & I2C_SMBSUS_IRQ irq
+ I2C_enable_smbus_irq( &g_i2c_inst, irq_to_enable );
+
+ // Get I2C IRQ type
+ pending_irq = I2C_get_irq_status( &g_i2c_inst );
+
+ // Let's assume, in system, INTR and SMBALERT IRQ is pending.
+ // So pending_irq will return status of both the IRQs
+
+ if( pending_irq & I2C_SMBALERT_IRQ )
+ {
+ // if true, it means SMBALERT_IRQ is there in pending IRQ list
+ }
+ if( pending_irq & I2C_INTR_IRQ )
+ {
+ // if true, it means I2C_INTR_IRQ is there in pending IRQ list
+ }
+ }
+ @endcode
+ */
+uint8_t I2C_get_irq_status
+(
+ i2c_instance_t * this_i2c
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_set_user_data() function is used to allow the association of a block
+ of application specific data with a CoreI2C channel. The composition of the
+ data block is an application matter and the driver simply provides the means
+ for the application to set and retrieve the pointer. This may for example be
+ used to provide additional channel specific information to the slave write
+ handler.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @param p_user_data:
+ The p_user_data parameter is a pointer to the user specific data block for
+ this channel. It is defined as void * as the driver does not know the actual
+ type of data being pointed to and simply stores the pointer for later
+ retrieval by the application.
+
+ @return
+ none.
+
+ Example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void I2C_set_user_data
+(
+ i2c_instance_t * this_i2c,
+ void * p_user_data
+);
+
+/*-------------------------------------------------------------------------*//**
+ The I2C_get_user_data() function is used to allow the retrieval of the address
+ of a block of application specific data associated with a CoreI2C channel.
+ The composition of the data block is an application matter and the driver
+ simply provides the means for the application to set and retrieve the pointer.
+ This may for example be used to provide additional channel specific
+ information to the slave write handler.
+ ------------------------------------------------------------------------------
+ @param this_i2c:
+ The this_i2c parameter is a pointer to the i2c_instance_t data structure
+ holding all data related to a specific CoreI2C channel. For example, if only
+ one channel is initialized, this data structure holds the information of
+ channel 0 of the instantiated CoreI2C hardware.
+
+ @return
+ This function returns a pointer to the user specific data block for this
+ channel. It is defined as void * as the driver does not know the actual type
+ of data being pointed. If no user data has been registered for this channel
+ a NULL pointer is returned.
+
+ Example
+ @code
+ #define COREI2C_BASE_ADDR 0xC0000000u
+ #define SLAVE_SER_ADDR 0x10u
+
+ i2c_instance_t g_i2c_inst;
+ app_data_t channel_xdata;
+
+ void main( void )
+ {
+ app_data_t *p_xdata;
+
+ I2C_init( &g_i2c_inst, COREI2C_BASE_ADDR, SLAVE_SER_ADDR,
+ I2C_PCLK_DIV_256 );
+
+ // Store location of user data in instance structure
+ I2C_set_user_data( &g_i2c_inst, (void *)&channel_xdata );
+
+ ...
+
+ // Retrieve location of user data and do some work on it
+ p_xdata = (app_data_t *)I2C_get_user_data( &g_i2c_inst );
+ if( NULL != p_xdata )
+ {
+ p_xdata->foo = 123;
+ }
+ }
+ @endcode
+ */
+void * I2C_get_user_data
+(
+ i2c_instance_t * this_i2c
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_smbus_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_smbus_regs.h
new file mode 100644
index 000000000..67da7a5af
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/core_smbus_regs.h
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 7984 $
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $
+ */
+
+#ifndef __CORE_SMBUS_REGISTERS
+#define __CORE_SMBUS_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * CONTROL register details
+ */
+#define CONTROL_REG_OFFSET 0x00u
+
+/*
+ * CR0 bits.
+ */
+#define CR0_OFFSET 0x00u
+#define CR0_MASK 0x01u
+#define CR0_SHIFT 0u
+
+/*
+ * CR1 bits.
+ */
+#define CR1_OFFSET 0x00u
+#define CR1_MASK 0x02u
+#define CR1_SHIFT 1u
+
+/*
+ * AA bits.
+ */
+#define AA_OFFSET 0x00u
+#define AA_MASK 0x04u
+#define AA_SHIFT 2u
+
+/*
+ * SI bits.
+ */
+#define SI_OFFSET 0x00u
+#define SI_MASK 0x08u
+#define SI_SHIFT 3u
+
+/*
+ * STO bits.
+ */
+#define STO_OFFSET 0x00u
+#define STO_MASK 0x10u
+#define STO_SHIFT 4u
+
+/*
+ * STA bits.
+ */
+#define STA_OFFSET 0x00u
+#define STA_MASK 0x20u
+#define STA_SHIFT 5u
+
+/*
+ * ENS1 bits.
+ */
+#define ENS1_OFFSET 0x00u
+#define ENS1_MASK 0x40u
+#define ENS1_SHIFT 6u
+
+/*
+ * CR2 bits.
+ */
+#define CR2_OFFSET 0x00u
+#define CR2_MASK 0x80u
+#define CR2_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * STATUS register details
+ */
+#define STATUS_REG_OFFSET 0x04u
+
+/*------------------------------------------------------------------------------
+ * DATA register details
+ */
+#define DATA_REG_OFFSET 0x08u
+
+/*
+ * TARGET_ADDR bits.
+ */
+#define TARGET_ADDR_OFFSET 0x08u
+#define TARGET_ADDR_MASK 0xFEu
+#define TARGET_ADDR_SHIFT 1u
+
+/*
+ * DIR bit.
+ */
+#define DIR_OFFSET 0x08u
+#define DIR_MASK 0x01u
+#define DIR_SHIFT 0u
+
+
+/*------------------------------------------------------------------------------
+ * ADDRESS register details
+ */
+#define ADDRESS_REG_OFFSET 0x0Cu
+
+/*
+ * GC bits.
+ */
+#define GC_OFFSET 0x0Cu
+#define GC_MASK 0x01u
+#define GC_SHIFT 0u
+
+/*
+ * ADR bits.
+ */
+#define OWN_SLAVE_ADDR_OFFSET 0x0Cu
+#define OWN_SLAVE_ADDR_MASK 0xFEu
+#define OWN_SLAVE_ADDR_SHIFT 1u
+
+/*------------------------------------------------------------------------------
+ * SMBUS register details
+ */
+#define SMBUS_REG_OFFSET 0x10u
+
+/*
+ * SMBALERT_IE bits.
+ */
+#define SMBALERT_IE_OFFSET 0x10u
+#define SMBALERT_IE_MASK 0x01u
+#define SMBALERT_IE_SHIFT 0u
+
+/*
+ * SMBSUS_IE bits.
+ */
+#define SMBSUS_IE_OFFSET 0x10u
+#define SMBSUS_IE_MASK 0x02u
+#define SMBSUS_IE_SHIFT 1u
+
+/*
+ * SMB_IPMI_EN bits.
+ */
+#define SMB_IPMI_EN_OFFSET 0x10u
+#define SMB_IPMI_EN_MASK 0x04u
+#define SMB_IPMI_EN_SHIFT 2u
+
+/*
+ * SMBALERT_NI_STATUS bits.
+ */
+#define SMBALERT_NI_STATUS_OFFSET 0x10u
+#define SMBALERT_NI_STATUS_MASK 0x08u
+#define SMBALERT_NI_STATUS_SHIFT 3u
+
+/*
+ * SMBALERT_NO_CONTROL bits.
+ */
+#define SMBALERT_NO_CONTROL_OFFSET 0x10u
+#define SMBALERT_NO_CONTROL_MASK 0x10u
+#define SMBALERT_NO_CONTROL_SHIFT 4u
+
+/*
+ * SMBSUS_NI_STATUS bits.
+ */
+#define SMBSUS_NI_STATUS_OFFSET 0x10u
+#define SMBSUS_NI_STATUS_MASK 0x20u
+#define SMBSUS_NI_STATUS_SHIFT 5u
+
+/*
+ * SMBSUS_NO_CONTROL bits.
+ */
+#define SMBSUS_NO_CONTROL_OFFSET 0x10u
+#define SMBSUS_NO_CONTROL_MASK 0x40u
+#define SMBSUS_NO_CONTROL_SHIFT 6u
+
+/*
+ * SMBUS_MST_RESET bits.
+ */
+#define SMBUS_MST_RESET_OFFSET 0x10u
+#define SMBUS_MST_RESET_MASK 0x80u
+#define SMBUS_MST_RESET_SHIFT 7u
+
+/*------------------------------------------------------------------------------
+ * SLAVE ADDRESS 1 register details
+ */
+
+#define ADDRESS1_REG_OFFSET 0x1Cu
+
+/*
+ * SLAVE1_EN bit of Slave Address 1 .
+ */
+#define SLAVE1_EN_OFFSET 0x1Cu
+#define SLAVE1_EN_MASK 0x01u
+#define SLAVE1_EN_SHIFT 0u
+
+#endif /* __CORE_SMBUS_REGISTERS */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/i2c_interrupt.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/i2c_interrupt.c
new file mode 100644
index 000000000..f918b8c9c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreI2C/i2c_interrupt.c
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * (c) Copyright 2009-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreI2C driver interrupt control.
+ *
+ * SVN $Revision: 7984 $
+ * SVN $Date: 2015-10-12 12:07:40 +0530 (Mon, 12 Oct 2015) $
+ */
+#include "hal.h"
+#include "hal_assert.h"
+#include "core_i2c.h"
+#include "riscv_hal.h"
+
+
+#define I2C_IRQn External_29_IRQn
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to enable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_enable_irq( i2c_instance_t * this_i2c )
+{
+ PLIC_EnableIRQ(I2C_IRQn);
+// HAL_ASSERT(0)
+}
+
+/*------------------------------------------------------------------------------
+ * This function must be modified to disable interrupts generated from the
+ * CoreI2C instance identified as parameter.
+ */
+void I2C_disable_irq( i2c_instance_t * this_i2c )
+{
+ PLIC_DisableIRQ(I2C_IRQn);
+// HAL_ASSERT(0)
+}
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.c
new file mode 100644
index 000000000..3f6720b16
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.c
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreTimer driver implementation.
+ *
+ * SVN $Revision: 7967 $
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $
+ */
+
+#include "core_timer.h"
+#include "coretimer_regs.h"
+#include "hal.h"
+#include "hal_assert.h"
+
+#ifndef NDEBUG
+static timer_instance_t* NULL_timer_instance;
+#endif
+
+/***************************************************************************//**
+ * TMR_init()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void
+TMR_init
+(
+ timer_instance_t * this_timer,
+ addr_t address,
+ uint8_t mode,
+ uint32_t prescale,
+ uint32_t load_value
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+ HAL_ASSERT( prescale <= PRESCALER_DIV_1024 )
+ HAL_ASSERT( load_value != 0 )
+
+ this_timer->base_address = address;
+
+ /* Disable interrupts. */
+ HAL_set_32bit_reg_field( address, InterruptEnable,0 );
+
+ /* Disable timer. */
+ HAL_set_32bit_reg_field( address, TimerEnable, 0 );
+
+ /* Clear pending interrupt. */
+ HAL_set_32bit_reg( address, TimerIntClr, 1 );
+
+ /* Configure prescaler and load value. */
+ HAL_set_32bit_reg( address, TimerPrescale, prescale );
+ HAL_set_32bit_reg( address, TimerLoad, load_value );
+
+ /* Set the interrupt mode. */
+ if ( mode == TMR_CONTINUOUS_MODE )
+ {
+ HAL_set_32bit_reg_field( address, TimerMode, 0 );
+ }
+ else
+ {
+ /* TMR_ONE_SHOT_MODE */
+ HAL_set_32bit_reg_field( address, TimerMode, 1 );
+ }
+}
+
+/***************************************************************************//**
+ * TMR_start()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void
+TMR_start
+(
+ timer_instance_t * this_timer
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+
+ HAL_set_32bit_reg_field( this_timer->base_address, TimerEnable, 1 );
+}
+
+/***************************************************************************//**
+ * TMR_stop()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void
+TMR_stop
+(
+ timer_instance_t * this_timer
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+
+ HAL_set_32bit_reg_field( this_timer->base_address, TimerEnable, 0 );
+}
+
+
+/***************************************************************************//**
+ * TMR_enable_int()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void
+TMR_enable_int
+(
+ timer_instance_t * this_timer
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+
+ HAL_set_32bit_reg_field( this_timer->base_address, InterruptEnable, 1 );
+}
+
+/***************************************************************************//**
+ * TMR_clear_int()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void
+TMR_clear_int
+(
+ timer_instance_t * this_timer
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+
+ HAL_set_32bit_reg( this_timer->base_address, TimerIntClr, 0x01 );
+}
+
+/***************************************************************************//**
+ * TMR_current_value()
+ * See "core_timer.h" for details of how to use this function.
+ */
+uint32_t
+TMR_current_value
+(
+ timer_instance_t * this_timer
+)
+{
+ uint32_t value = 0;
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+
+ value = HAL_get_32bit_reg( this_timer->base_address, TimerValue );
+
+ return value;
+}
+
+/***************************************************************************//**
+ * TMR_reload()
+ * See "core_timer.h" for details of how to use this function.
+ */
+void TMR_reload
+(
+ timer_instance_t * this_timer,
+ uint32_t load_value
+)
+{
+ HAL_ASSERT( this_timer != NULL_timer_instance )
+ HAL_ASSERT( load_value != 0 )
+
+ HAL_set_32bit_reg(this_timer->base_address, TimerLoad, load_value );
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.h
new file mode 100644
index 000000000..04b7a6e97
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/core_timer.h
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreTimer public API.
+ *
+ * SVN $Revision: 7967 $
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $
+ */
+#ifndef CORE_TIMER_H_
+#define CORE_TIMER_H_
+
+#include "cpu_types.h"
+
+/***************************************************************************//**
+ * The following definitions are used to select the CoreTimer driver operating
+ * mode. They allow selecting continuous or one-shot mode.
+ * 1. Continuous Mode
+ * In continuous mode the timer's counter is decremented from the load value
+ * until it reaches zero. The timer counter is automatically reloaded, with the
+ * load value, upon reaching zero. An interrupt is generated every time the
+ * counter reaches zero if interrupt is enabled.
+ * This mode is typically used to generate an interrupt at constant time
+ * intervals.
+ * 2. One-shot mode:
+ * In one-shot mode, the counter decrements from the load value and until it
+ * reaches zero. An interrupt can be generated, if enabled, when the counter
+ * reaches zero. The timer's counter must be reloaded to begin counting down
+ * again.
+ */
+#define TMR_CONTINUOUS_MODE 0
+#define TMR_ONE_SHOT_MODE 1
+
+/***************************************************************************//**
+ * The following definitions are used to configure the CoreTimer prescaler.
+ * The prescaler is used to divide down the clock used to decrement the
+ * CoreTimer counter. It can be configure to divide the clock by 2, 4, 8,
+ * 16, 32, 64, 128, 256, 512, or 1024.
+ */
+#define PRESCALER_DIV_2 0
+#define PRESCALER_DIV_4 1
+#define PRESCALER_DIV_8 2
+#define PRESCALER_DIV_16 3
+#define PRESCALER_DIV_32 4
+#define PRESCALER_DIV_64 5
+#define PRESCALER_DIV_128 6
+#define PRESCALER_DIV_256 7
+#define PRESCALER_DIV_512 8
+#define PRESCALER_DIV_1024 9
+
+/***************************************************************************//**
+ * There should be one instance of this structure for each instance of CoreTimer
+ * in your system. The function TMR_init() initializes this structure. It is
+ * used to identify the various CoreTimer hardware instances in your system.
+ * An initialized timer instance structure should be passed as first parameter to
+ * CoreTimer driver functions to identify which CoreTimer instance should perform
+ * the requested operation.
+ * Software using this driver should only need to create one single instance of
+ * this data structure for each hardware timer instance in the system.
+ */
+typedef struct __timer_instance_t
+{
+ addr_t base_address;
+} timer_instance_t;
+
+/***************************************************************************//**
+ * The function TMR_init() initializes the data structures and sets relevant
+ * CoreTimer registers. This function will prepare the Timer for use in a given
+ * hardware/software configuration. It should be called before any other Timer
+ * API functions.
+ * The timer will not start counting down immediately after this function is
+ * called. It is necessary to call TMR_start() to start the timer decrementing.
+ * The CoreTimer interrupt is disabled as part of this function.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer will be used to identify the
+ * target CoreTimer hardware instance in subsequent calls
+ * to the CoreTimer functions.
+ * @param address Base address in the processor's memory map of the
+ * registers of the CoreTimer instance being initialized.
+ * @param mode This parameter is used to select the operating mode of
+ * the timer driver. This can be either TMR_CONTINUOUS_MODE
+ * or TMR_ONE_SHOT_MODE.
+ * @param prescale This parameter is used to select the prescaler divider
+ * used to divide down the clock used to decrement the
+ * timer’s counter. This can be set using one of the
+ * PRESCALER_DIV_ definitions, where is the
+ * divider’s value.
+ * @param load_value This parameter is used to set the timer’s load value
+ * from which the CoreTimer counter will decrement.
+ * In Continuous mode, this value will be used to reload
+ * the timer’s counter whenever it reaches zero.
+ */
+void
+TMR_init
+(
+ timer_instance_t * this_timer,
+ addr_t address,
+ uint8_t mode,
+ uint32_t prescale,
+ uint32_t load_value
+);
+
+/***************************************************************************//**
+ * The function TMR_start() enables the timer to start counting down.
+ * This function only needs to be called once after the timer has been
+ * initialized through a call to TMR_init(). It does not need to be called after
+ * each call to TMR_reload() when the timer is used in one-shot mode.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ */
+void
+TMR_start
+(
+ timer_instance_t * this_timer
+);
+
+/***************************************************************************//**
+ * The function TMR_stop() stops the timer counting down. It can be used to
+ * stop interrupts from being generated when continuous mode is used and
+ * interrupts must be paused from being generated.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ */
+void
+TMR_stop
+(
+ timer_instance_t * this_timer
+);
+
+/***************************************************************************//**
+ * The function TMR_enable_int() enables the timer interrupt. A call to this
+ * function will allow the interrupt signal coming out of CoreTimer to be
+ * asserted.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ */
+void
+TMR_enable_int
+(
+ timer_instance_t * this_timer
+);
+
+/***************************************************************************//**
+ * The function TMR_clear_int() clears the timer interrupt. This function should
+ * be called within the interrupt handler servicing interrupts from the timer.
+ * Failure to clear the timer interrupt will result in the interrupt signal
+ * generating from CoreTimer to remain asserted. This assertion may cause the
+ * interrupt service routine to be continuously called, causing the system to
+ * lock up.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ */
+void
+TMR_clear_int
+(
+ timer_instance_t * this_timer
+);
+
+/***************************************************************************//**
+ * The TMR_current_value() function returns the current value of the counter.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ *
+ * @return Returns the current value of the timer counter value.
+ */
+uint32_t
+TMR_current_value
+(
+ timer_instance_t * this_timer
+);
+
+/***************************************************************************//**
+ * The TMR_reload() function is used in one-shot mode. It reloads the timer
+ * counter with the values passed as parameter. This will result in an interrupt
+ * being generated when the timer counter reaches 0 if interrupt is enabled.
+ *
+ * @param this_timer Pointer to a timer_instance_t structure holding all
+ * relevant data associated with the target timer hardware
+ * instance. This pointer is used to identify the target
+ * CoreTimer hardware instance.
+ * @param load_value This parameter sets the value from which the CoreTimer
+ * counter will decrement.
+ */
+void TMR_reload
+(
+ timer_instance_t * this_timer,
+ uint32_t load_value
+);
+
+#endif /* CORE_TIMER_H_ */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/coretimer_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/coretimer_regs.h
new file mode 100644
index 000000000..5d7c67da2
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreTimer/coretimer_regs.h
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2015 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 7967 $
+ * SVN $Date: 2015-10-09 18:48:26 +0530 (Fri, 09 Oct 2015) $
+ */
+
+#ifndef __CORE_TIMER_REGISTERS
+#define __CORE_TIMER_REGISTERS 1
+
+/*------------------------------------------------------------------------------
+ * TimerLoad register details
+ */
+#define TimerLoad_REG_OFFSET 0x00
+
+/*
+ * LoadValue bits.
+ */
+#define LoadValue_OFFSET 0x00
+#define LoadValue_MASK 0xFFFFFFFF
+#define LoadValue_SHIFT 0
+
+/*------------------------------------------------------------------------------
+ * TimerValue register details
+ */
+#define TimerValue_REG_OFFSET 0x04
+
+/*
+ * CurrentValue bits.
+ */
+#define CurrentValue_OFFSET 0x04
+#define CurrentValue_MASK 0xFFFFFFFF
+#define CurrentValue_SHIFT 0
+
+/*------------------------------------------------------------------------------
+ * TimerControl register details
+ */
+#define TimerControl_REG_OFFSET 0x08
+
+/*
+ * TimerEnable bits.
+ */
+#define TimerEnable_OFFSET 0x08
+#define TimerEnable_MASK 0x00000001
+#define TimerEnable_SHIFT 0
+
+/*
+ * InterruptEnable bits.
+ */
+#define InterruptEnable_OFFSET 0x08
+#define InterruptEnable_MASK 0x00000002
+#define InterruptEnable_SHIFT 1
+
+/*
+ * TimerMode bits.
+ */
+#define TimerMode_OFFSET 0x08
+#define TimerMode_MASK 0x00000004
+#define TimerMode_SHIFT 2
+
+/*------------------------------------------------------------------------------
+ * TimerPrescale register details
+ */
+#define TimerPrescale_REG_OFFSET 0x0C
+
+/*
+ * Prescale bits.
+ */
+#define Prescale_OFFSET 0x0C
+#define Prescale_MASK 0x0000000F
+#define Prescale_SHIFT 0
+
+/*------------------------------------------------------------------------------
+ * TimerIntClr register details
+ */
+#define TimerIntClr_REG_OFFSET 0x10
+
+/*
+ * TimerIntClr bits.
+ */
+#define TimerIntClr_OFFSET 0x10
+#define TimerIntClr_MASK 0xFFFFFFFF
+#define TimerIntClr_SHIFT 0
+
+/*------------------------------------------------------------------------------
+ * TimerRIS register details
+ */
+#define TimerRIS_REG_OFFSET 0x14
+
+/*
+ * RawTimerInterrupt bits.
+ */
+#define RawTimerInterrupt_OFFSET 0x14
+#define RawTimerInterrupt_MASK 0x00000001
+#define RawTimerInterrupt_SHIFT 0
+
+/*------------------------------------------------------------------------------
+ * TimerMIS register details
+ */
+#define TimerMIS_REG_OFFSET 0x18
+
+/*
+ * TimerInterrupt bits.
+ */
+#define TimerInterrupt_OFFSET 0x18
+#define TimerInterrupt_MASK 0x00000001
+#define TimerInterrupt_SHIFT 0
+
+#endif /* __CORE_TIMER_REGISTERS */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.c
new file mode 100644
index 000000000..b4f40dc1e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.c
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.
+ *
+ * CoreUARTapb driver implementation. See file "core_uart_apb.h" for a
+ * description of the functions implemented in this file.
+ *
+ * SVN $Revision: 9082 $
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $
+ */
+#include "hal.h"
+#include "coreuartapb_regs.h"
+#include "core_uart_apb.h"
+#include "hal_assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_INSTANCE ( ( UART_instance_t* ) 0 )
+#define NULL_BUFFER ( ( uint8_t* ) 0 )
+
+#define MAX_LINE_CONFIG ( ( uint8_t )( DATA_8_BITS | ODD_PARITY ) )
+#define MAX_BAUD_VALUE ( ( uint16_t )( 0x1FFF ) )
+#define STATUS_ERROR_MASK ( ( uint8_t )( STATUS_PARITYERR_MASK | \
+ STATUS_OVERFLOW_MASK | \
+ STATUS_FRAMERR_MASK ) )
+#define BAUDVALUE_LSB ( (uint16_t) (0x00FF) )
+#define BAUDVALUE_MSB ( (uint16_t) (0xFF00) )
+#define BAUDVALUE_SHIFT ( (uint8_t) (5) )
+
+#define STATUS_ERROR_OFFSET STATUS_PARITYERR_SHIFT
+
+/***************************************************************************//**
+ * UART_init()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_init
+(
+ UART_instance_t * this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+)
+{
+ uint8_t rx_full;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( line_config <= MAX_LINE_CONFIG )
+ HAL_ASSERT( baud_value <= MAX_BAUD_VALUE )
+
+ if( ( this_uart != NULL_INSTANCE ) &&
+ ( line_config <= MAX_LINE_CONFIG ) &&
+ ( baud_value <= MAX_BAUD_VALUE ) )
+ {
+ /*
+ * Store lower 8-bits of baud value in CTRL1.
+ */
+ HAL_set_8bit_reg( base_addr, CTRL1, (uint_fast8_t)(baud_value &
+ BAUDVALUE_LSB ) );
+
+ /*
+ * Extract higher 5-bits of baud value and store in higher 5-bits
+ * of CTRL2, along with line configuration in lower 3 three bits.
+ */
+ HAL_set_8bit_reg( base_addr, CTRL2, (uint_fast8_t)line_config |
+ (uint_fast8_t)((baud_value &
+ BAUDVALUE_MSB) >> BAUDVALUE_SHIFT ) );
+
+ this_uart->base_address = base_addr;
+#ifndef NDEBUG
+ {
+ uint8_t config;
+ uint8_t temp;
+ uint16_t baud_val;
+ baud_val = HAL_get_8bit_reg( this_uart->base_address, CTRL1 );
+ config = HAL_get_8bit_reg( this_uart->base_address, CTRL2 );
+ /*
+ * To resolve operator precedence between & and <<
+ */
+ temp = ( config & (uint8_t)(CTRL2_BAUDVALUE_MASK ) );
+ baud_val |= (uint16_t)( (uint16_t)(temp) << BAUDVALUE_SHIFT );
+ config &= (uint8_t)(~CTRL2_BAUDVALUE_MASK);
+ HAL_ASSERT( baud_val == baud_value );
+ HAL_ASSERT( config == line_config );
+ }
+#endif
+
+ /*
+ * Flush the receive FIFO of data that may have been received before the
+ * driver was initialized.
+ */
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_RXFULL_MASK;
+ while ( rx_full )
+ {
+ HAL_get_8bit_reg( this_uart->base_address, RXDATA );
+ rx_full = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_RXFULL_MASK;
+ }
+
+ /*
+ * Clear status of the UART instance.
+ */
+ this_uart->status = (uint8_t)0;
+ }
+}
+
+/***************************************************************************//**
+ * UART_send()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_send
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ size_t char_idx;
+ uint8_t tx_ready;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )
+ HAL_ASSERT( tx_size > 0 )
+
+ if( (this_uart != NULL_INSTANCE) &&
+ (tx_buffer != NULL_BUFFER) &&
+ (tx_size > (size_t)0) )
+ {
+ for ( char_idx = (size_t)0; char_idx < tx_size; char_idx++ )
+ {
+ /* Wait for UART to become ready to transmit. */
+ do {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( !tx_ready );
+ /* Send next character in the buffer. */
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)tx_buffer[char_idx] );
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_fill_tx_fifo()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+size_t
+UART_fill_tx_fifo
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+)
+{
+ uint8_t tx_ready;
+ size_t size_sent = 0u;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( tx_buffer != NULL_BUFFER )
+ HAL_ASSERT( tx_size > 0 )
+
+ /* Fill the UART's Tx FIFO until the FIFO is full or the complete input
+ * buffer has been written. */
+ if( (this_uart != NULL_INSTANCE) &&
+ (tx_buffer != NULL_BUFFER) &&
+ (tx_size > 0u) )
+ {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ if ( tx_ready )
+ {
+ do {
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)tx_buffer[size_sent] );
+ size_sent++;
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( (tx_ready) && ( size_sent < tx_size ) );
+ }
+ }
+ return size_sent;
+}
+
+/***************************************************************************//**
+ * UART_get_rx()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+size_t
+UART_get_rx
+(
+ UART_instance_t * this_uart,
+ uint8_t * rx_buffer,
+ size_t buff_size
+)
+{
+ uint8_t new_status;
+ uint8_t rx_full;
+ size_t rx_idx = 0u;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( rx_buffer != NULL_BUFFER )
+ HAL_ASSERT( buff_size > 0 )
+
+ if( (this_uart != NULL_INSTANCE) &&
+ (rx_buffer != NULL_BUFFER) &&
+ (buff_size > 0u) )
+ {
+ rx_idx = 0u;
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
+ this_uart->status |= new_status;
+ rx_full = new_status & STATUS_RXFULL_MASK;
+ while ( ( rx_full ) && ( rx_idx < buff_size ) )
+ {
+ rx_buffer[rx_idx] = HAL_get_8bit_reg( this_uart->base_address,
+ RXDATA );
+ rx_idx++;
+ new_status = HAL_get_8bit_reg( this_uart->base_address, STATUS );
+ this_uart->status |= new_status;
+ rx_full = new_status & STATUS_RXFULL_MASK;
+ }
+ }
+ return rx_idx;
+}
+
+/***************************************************************************//**
+ * UART_polled_tx_string()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+void
+UART_polled_tx_string
+(
+ UART_instance_t * this_uart,
+ const uint8_t * p_sz_string
+)
+{
+ uint32_t char_idx;
+ uint8_t tx_ready;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ HAL_ASSERT( p_sz_string != NULL_BUFFER )
+
+ if( ( this_uart != NULL_INSTANCE ) && ( p_sz_string != NULL_BUFFER ) )
+ {
+ char_idx = 0U;
+ while( 0U != p_sz_string[char_idx] )
+ {
+ /* Wait for UART to become ready to transmit. */
+ do {
+ tx_ready = HAL_get_8bit_reg( this_uart->base_address, STATUS ) &
+ STATUS_TXRDY_MASK;
+ } while ( !tx_ready );
+ /* Send next character in the buffer. */
+ HAL_set_8bit_reg( this_uart->base_address, TXDATA,
+ (uint_fast8_t)p_sz_string[char_idx] );
+ char_idx++;
+ }
+ }
+}
+
+/***************************************************************************//**
+ * UART_get_rx_status()
+ * See "core_uart_apb.h" for details of how to use this function.
+ */
+uint8_t
+UART_get_rx_status
+(
+ UART_instance_t * this_uart
+)
+{
+ uint8_t status = UART_APB_INVALID_PARAM;
+
+ HAL_ASSERT( this_uart != NULL_INSTANCE )
+ /*
+ * Extract UART error status and place in lower bits of "status".
+ * Bit 0 - Parity error status
+ * Bit 1 - Overflow error status
+ * Bit 2 - Frame error status
+ */
+ if( this_uart != NULL_INSTANCE )
+ {
+ status = ( ( this_uart->status & STATUS_ERROR_MASK ) >>
+ STATUS_ERROR_OFFSET );
+ /*
+ * Clear the sticky status for this instance.
+ */
+ this_uart->status = (uint8_t)0;
+ }
+ return status;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.h
new file mode 100644
index 000000000..680b68d5b
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/core_uart_apb.h
@@ -0,0 +1,407 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.
+ *
+ * This file contains the application programming interface for the CoreUARTapb
+ * bare metal driver.
+ *
+ * SVN $Revision: 9082 $
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $
+ */
+/*=========================================================================*//**
+ @mainpage CoreUARTapb Bare Metal Driver.
+
+ @section intro_sec Introduction
+ CoreUARTapb is an implementation of the Universal Asynchronous
+ Receiver/Transmitter aimed at a minimal FPGA tile usage within an Microsemi
+ FPGA. The CoreUARTapb bare metal software driver is designed for use in
+ systems with no operating system.
+
+ The CoreUARTapb driver provides functions for basic polled transmitting and
+ receiving operations. It also provides functions allowing use of the
+ CoreUARTapb in interrupt-driven mode, but leaves the management of interrupts
+ to the calling application, as interrupt enabling and disabling cannot be
+ controlled through the CoreUARTapb registers. The CoreUARTapb driver is
+ provided as C source code.
+
+ @section driver_configuration Driver Configuration
+ Your application software should configure the CoreUARTapb driver, through
+ calls to the UART_init() function for each CoreUARTapb instance in the
+ hardware design. The configuration parameters include the CoreUARTapb
+ hardware instance base address and other runtime parameters, such as baud
+ rate, bit width, and parity. No CoreUARTapb hardware configuration parameters
+ are needed by the driver, apart from the CoreUARTapb hardware instance base
+ address. Hence, no additional configuration files are required to use the driver.
+
+ A CoreUARTapb hardware instance can be generated with fixed baud value,
+ character size and parity configuration settings as part of the hardware flow.
+ The baud_value and line_config parameter values passed to the UART_init()
+ function will not have any effect if fixed values were selected for the
+ baud value, character size and parity in the hardware configuration of
+ CoreUARTapb. When fixed values are selected for these hardware configuration
+ parameters, the driver cannot overwrite the fixed values in the CoreUARTapb
+ control registers, CTRL1 and CTRL2.
+
+ @section theory_op Theory of Operation
+ The CoreUARTapb software driver is designed to allow the control of multiple
+ instances of CoreUARTapb. Each instance of CoreUARTapb in the hardware design
+ is associated with a single instance of the UART_instance_t structure in the
+ software. You need to allocate memory for one unique UART_instance_t
+ structure instance for each CoreUARTapb hardware instance. The contents of
+ these data structures are initialized during calls to function UART_init().
+ A pointer to the structure is passed to subsequent driver functions in order
+ to identify the CoreUARTapb hardware instance you wish to perform the
+ requested operation on.
+
+ Note: Do not attempt to directly manipulate the content of UART_instance_t
+ structures. This structure is only intended to be modified by the driver
+ function.
+
+ The driver can be used to transmit and receive data once initialized.
+ Transmit can be performed using the UART_send() function. This function
+ is blocking, meaning that it will only return once the data passed to
+ the function has been sent to the CoreUARTapb hardware. Data received
+ by the CoreUARTapb hardware can be read by the user application using
+ the UART_get_rx() function.
+
+ The function UART_fill_tx_fifo() is also provided to be used as part of
+ interrupt-driven transmit. This function fills the CoreUARTapb hardware
+ transmit FIFO with the content of a data buffer passed as a parameter before
+ returning. The control of the interrupts must be implemented outside the
+ driver as the CoreUARTapb hardware does not provide the ability to enable
+ or disable its interrupt sources.
+
+ The function UART_polled_tx_string() is provided to transmit a NULL
+ terminated string in polled mode. This function is blocking, meaning that it
+ will only return once the data passed to the function has been sent to the
+ CoreUARTapb hardware.
+
+ The function UART_get_rx_status() returns the error status of the CoreUARTapb
+ receiver. This can be used by applications to take appropriate action in case
+ of receiver errors.
+*//*=========================================================================*/
+#ifndef __CORE_UART_APB_H
+#define __CORE_UART_APB_H 1
+
+#include "cpu_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/***************************************************************************//**
+ * Data bits length defines:
+ */
+#define DATA_7_BITS 0x00u
+#define DATA_8_BITS 0x01u
+
+/***************************************************************************//**
+ * Parity defines:
+ */
+#define NO_PARITY 0x00u
+#define EVEN_PARITY 0x02u
+#define ODD_PARITY 0x06u
+
+/***************************************************************************//**
+ * Error Status definitions:
+ */
+#define UART_APB_PARITY_ERROR 0x01u
+#define UART_APB_OVERFLOW_ERROR 0x02u
+#define UART_APB_FRAMING_ERROR 0x04u
+#define UART_APB_NO_ERROR 0x00u
+#define UART_APB_INVALID_PARAM 0xFFu
+
+/***************************************************************************//**
+ * UART_instance_t
+ *
+ * There should be one instance of this structure for each instance of CoreUARTapb
+ * in your system. This structure instance is used to identify the various UARTs
+ * in a system and should be passed as first parameter to UART functions to
+ * identify which UART should perform the requested operation. The 'status'
+ * element in the structure is used to provide sticky status information.
+ */
+typedef struct
+{
+ addr_t base_address;
+ uint8_t status;
+} UART_instance_t;
+
+/***************************************************************************//**
+ * The function UART_init() initializes the UART with the configuration passed
+ * as parameters. The configuration parameters are the baud_value used to
+ * generate the baud rate and the line configuration (bit length and parity).
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the CoreUARTapb. This pointer will be used to identify
+ * the target CoreUARTapb hardware instance in subsequent
+ * calls to the CoreUARTapb functions.
+ * @param base_addr The base_address parameter is the base address in the
+ * processor's memory map for the registers of the
+ * CoreUARTapb instance being initialized.
+ * @param baud_value The baud_value parameter is used to select the baud rate
+ * for the UART. The baud value is calculated from the
+ * frequency of the system clock in hertz and the desired
+ * baud rate using the following equation:
+ *
+ * baud_value = (clock /(baud_rate * 16)) - 1.
+ *
+ * The baud_value parameter must be a value in the range 0
+ * to 8191 (or 0x0000 to 0x1FFF).
+ * @param line_config This parameter is the line configuration specifying the
+ * bit length and parity settings. This is a logical OR of:
+ * - DATA_7_BITS
+ * - DATA_8_BITS
+ * - NO_PARITY
+ * - EVEN_PARITY
+ * - ODD_PARITY
+ * For example, 8 bits even parity would be specified as
+ * (DATA_8_BITS | EVEN_PARITY).
+ * @return This function does not return a value.
+ * Example:
+ * @code
+ * #define BAUD_VALUE_57600 25
+ *
+ * #define COREUARTAPB0_BASE_ADDR 0xC3000000UL
+ *
+ * UART_instance_t g_uart;
+ * int main()
+ * {
+ * UART_init(&g_uart, COREUARTAPB0_BASE_ADDR,
+ BAUD_VALUE_57600, (DATA_8_BITS | EVEN_PARITY));
+ * }
+ * @endcode
+ */
+void
+UART_init
+(
+ UART_instance_t * this_uart,
+ addr_t base_addr,
+ uint16_t baud_value,
+ uint8_t line_config
+);
+
+/***************************************************************************//**
+ * The function UART_send() is used to transmit data. It transfers the contents
+ * of the transmitter data buffer, passed as a function parameter, into the
+ * UART's hardware transmitter FIFO. It returns when the full content of the
+ * transmitter data buffer has been transferred to the UART's transmitter FIFO.
+ *
+ * Note: you cannot assume that the data you are sending using this function has
+ * been received at the other end by the time this function returns. The actual
+ * transmit over the serial connection will still be taking place at the time of
+ * the function return. It is safe to release or reuse the memory used as the
+ * transmit buffer once this function returns.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * UART_instance_t structure which holds all data regarding
+ * this instance of the CoreUARTapbUART.
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer
+ * containing the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size, in bytes, of
+ * the data to be transmitted.
+ *
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\n\r\n\r\n\rUART_send() test message 1"};
+ * UART_send(&g_uart,(const uint8_t *)&testmsg1,sizeof(testmsg1));
+ * @endcode
+ */
+void
+UART_send
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ * The function UART_fill_tx_fifo() fills the UART's transmitter hardware FIFO
+ * with the data found in the transmitter buffer that is passed in as a
+ * function parameter. The function returns either when the FIFO is full or
+ * when the complete contents of the transmitter buffer have been copied into
+ * the FIFO. It returns the number of bytes copied into the UART's transmitter
+ * hardware FIFO. This function is intended to be used as part of
+ * interrupt-driven transmission.
+ *
+ * Note: You cannot assume that the data you transmit using this function has
+ * been received at the other end by the time this function returns.
+ * The actual transmission over the serial connection will still be
+ * taking place at the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the UART.
+ * @param tx_buffer The tx_buffer parameter is a pointer to a buffer
+ * containing the data to be transmitted.
+ * @param tx_size The tx_size parameter is the size in bytes, of the data
+ * to be transmitted.
+ * @return This function returns the number of bytes copied
+ * into the UART's transmitter hardware FIFO.
+ *
+ * Example:
+ * @code
+ * void send_using_interrupt
+ * (
+ * uint8_t * pbuff,
+ * size_t tx_size
+ * )
+ * {
+ * size_t size_in_fifo;
+ * size_in_fifo = UART_fill_tx_fifo( &g_uart, pbuff, tx_size );
+ * }
+ * @endcode
+ */
+size_t
+UART_fill_tx_fifo
+(
+ UART_instance_t * this_uart,
+ const uint8_t * tx_buffer,
+ size_t tx_size
+);
+
+/***************************************************************************//**
+ * The function UART_get_rx() reads the content of the UART's receiver hardware
+ * FIFO and stores it in the receiver buffer that is passed in as a function
+ * parameter. It copies either the full contents of the FIFO into the receiver
+ * buffer, or just enough data from the FIFO to fill the receiver buffer,
+ * dependent upon the size of the receiver buffer. The size of the receiver
+ * buffer is passed in as a function parameter. UART_get_rx() returns the number
+ * of bytes copied into the receiver buffer. If no data was received at the time
+ * the function is called, the function returns 0.
+ *
+ * Note: This function reads and accumulates the receiver status of the
+ * CoreUARTapb instance before reading each byte from the receiver's
+ * data register/FIFO. This allows the driver to maintain a sticky
+ * record of any receiver errors that occur as the UART receives each
+ * data byte; receiver errors would otherwise be lost after each read
+ * from the receiver's data register. A call to the UART_get_rx_status()
+ * function returns any receiver errors accumulated during the execution
+ * of the UART_get_rx() function.
+ * Note: When FIFO mode is disabled in the CoreUARTapb hardware configuration,
+ * the driver accumulates a sticky record of any parity errors, framing
+ * errors or overflow errors. When FIFO mode is enabled, the driver
+ * accumulates a sticky record of overflow errors only; in this case
+ * interrupts must be used to handle parity errors or framing errors.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance of
+ * the UART.
+ * @param rx_buffer The rx_buffer parameter is a pointer to a buffer where the
+ * received data will be copied.
+ * @param buff_size The buff_size parameter is the size of the receive buffer
+ * in bytes.
+ * @return This function returns the number of bytes copied into the
+ * receive buffer.
+ *
+ * Example:
+ * @code
+ * #define MAX_RX_DATA_SIZE 256
+ *
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t rx_size = 0;
+ *
+ * rx_size = UART_get_rx( &g_uart, rx_data, sizeof(rx_data) );
+ * @endcode
+ */
+size_t
+UART_get_rx
+(
+ UART_instance_t * this_uart,
+ uint8_t * rx_buffer,
+ size_t buff_size
+);
+
+/***************************************************************************//**
+ * The function UART_polled_tx_string() is used to transmit a NULL ('\0')
+ * terminated string. Internally, it polls for the transmit ready status and
+ * transfers the text starting at the address pointed to by p_sz_string into
+ * the UART's hardware transmitter FIFO. It is a blocking function and returns
+ * only when the complete string has been transferred to the UART's transmit
+ * FIFO.
+ *
+ * Note: You cannot assume that the data you transmit using this function
+ * has been received at the other end by the time this function
+ * returns. The actual transmission over the serial connection will
+ * still be taking place at the time of the function return.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a
+ * UART_instance_t structure which holds
+ * all data regarding this instance of the UART.
+ * @param p_sz_string The p_sz_string parameter is a pointer to a buffer
+ * containing the NULL ('\0') terminated string to be
+ * transmitted.
+ * @return This function does not return a value.
+ *
+ * Example:
+ * @code
+ * uint8_t testmsg1[] = {"\r\n\r\nUART_polled_tx_string() test message 1\0"};
+ * UART_polled_tx_string(&g_uart,(const uint8_t *)&testmsg1);
+ * @endcode
+ */
+void
+UART_polled_tx_string
+(
+ UART_instance_t * this_uart,
+ const uint8_t * p_sz_string
+);
+
+/***************************************************************************//**
+ * The UART_get_rx_status() function returns the receiver error status of the
+ * CoreUARTapb instance. It reads both the current error status of the receiver
+ * and the accumulated error status from preceding calls to the UART_get_rx()
+ * function and combines them using a bitwise OR. It returns the cumulative
+ * parity, framing and overflow error status of the receiver, since the
+ * previous call to UART_get_rx_status(), as an 8-bit encoded value.
+ *
+ * Note: The UART_get_rx() function reads and accumulates the receiver status
+ * of the CoreUARTapb instance before reading each byte from the
+ * receiver's data register/FIFO. The driver maintains a sticky record
+ * of the cumulative error status, which persists after the
+ * UART_get_rx() function returns. The UART_get_rx_status() function
+ * clears this accumulated record of receiver errors before returning.
+ *
+ * @param this_uart The this_uart parameter is a pointer to a UART_instance_t
+ * structure which holds all data regarding this instance
+ * of the UART.
+ * @return This function returns the UART receiver error status as
+ * an 8-bit encoded value. The returned value is 0 if no
+ * receiver errors occurred. The driver provides a set of
+ * bit mask constants which should be compared with and/or
+ * used to mask the returned value to determine the
+ * receiver error status.
+ * When the return value is compared to the following bit
+ * masks, a non-zero result indicates that the
+ * corresponding error occurred:
+ * UART_APB_PARITY_ERROR (bit mask = 0x01)
+ * UART_APB_OVERFLOW_ERROR (bit mask = 0x02)
+ * UART_APB_FRAMING_ERROR (bit mask = 0x04)
+ * When the return value is compared to the following bit
+ * mask, a non-zero result indicates that no error occurred:
+ * UART_APB_NO_ERROR (0x00)
+ *
+ * Example:
+ * @code
+ * UART_instance_t g_uart;
+ * uint8_t rx_data[MAX_RX_DATA_SIZE];
+ * uint8_t err_status;
+ * err_status = UART_get_err_status(&g_uart);
+ *
+ * if(UART_APB_NO_ERROR == err_status )
+ * {
+ * rx_size = UART_get_rx( &g_uart, rx_data, MAX_RX_DATA_SIZE );
+ * }
+ * @endcode
+ */
+uint8_t
+UART_get_rx_status
+(
+ UART_instance_t * this_uart
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_UART_APB_H */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/coreuartapb_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/coreuartapb_regs.h
new file mode 100644
index 000000000..e6cc8c1da
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/drivers/CoreUARTapb/coreuartapb_regs.h
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2017 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 9082 $
+ * SVN $Date: 2017-04-28 11:51:36 +0530 (Fri, 28 Apr 2017) $
+ */
+
+#ifndef __CORE_UART_APB_REGISTERS
+#define __CORE_UART_APB_REGISTERS 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*------------------------------------------------------------------------------
+ * TxData register details
+ */
+#define TXDATA_REG_OFFSET 0x0u
+
+/*
+ * TxData bits.
+ */
+#define TXDATA_OFFSET 0x0u
+#define TXDATA_MASK 0xFFu
+#define TXDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * RxData register details
+ */
+#define RXDATA_REG_OFFSET 0x4u
+
+/*
+ * RxData bits.
+ */
+#define RXDATA_OFFSET 0x4u
+#define RXDATA_MASK 0xFFu
+#define RXDATA_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * ControReg1 register details
+ */
+#define CTRL1_REG_OFFSET 0x8u
+
+/*
+ * Baud value (Lower 8-bits)
+ */
+#define CTRL1_BAUDVALUE_OFFSET 0x8u
+#define CTRL1_BAUDVALUE_MASK 0xFFu
+#define CTRL1_BAUDVALUE_SHIFT 0u
+
+/*------------------------------------------------------------------------------
+ * ControReg2 register details
+ */
+#define CTRL2_REG_OFFSET 0xCu
+
+/*
+ * Bit length
+ */
+#define CTRL2_BIT_LENGTH_OFFSET 0xCu
+#define CTRL2_BIT_LENGTH_MASK 0x01u
+#define CTRL2_BIT_LENGTH_SHIFT 0u
+
+/*
+ * Parity enable.
+ */
+#define CTRL2_PARITY_EN_OFFSET 0xCu
+#define CTRL2_PARITY_EN_MASK 0x02u
+#define CTRL2_PARITY_EN_SHIFT 1u
+
+/*
+ * Odd/even parity selection.
+ */
+#define CTRL2_ODD_EVEN_OFFSET 0xCu
+#define CTRL2_ODD_EVEN_MASK 0x04u
+#define CTRL2_ODD_EVEN_SHIFT 2u
+
+/*
+ * Baud value (Higher 5-bits)
+ */
+#define CTRL2_BAUDVALUE_OFFSET 0xCu
+#define CTRL2_BAUDVALUE_MASK 0xF8u
+#define CTRL2_BAUDVALUE_SHIFT 3u
+
+/*------------------------------------------------------------------------------
+ * StatusReg register details
+ */
+#define StatusReg_REG_OFFSET 0x10u
+
+#define STATUS_REG_OFFSET 0x10u
+
+/*
+ * Transmit ready.
+ */
+#define STATUS_TXRDY_OFFSET 0x10u
+#define STATUS_TXRDY_MASK 0x01u
+#define STATUS_TXRDY_SHIFT 0u
+
+/*
+ * Receive full.
+ */
+#define STATUS_RXFULL_OFFSET 0x10u
+#define STATUS_RXFULL_MASK 0x02u
+#define STATUS_RXFULL_SHIFT 1u
+
+/*
+ * Parity error.
+ */
+#define STATUS_PARITYERR_OFFSET 0x10u
+#define STATUS_PARITYERR_MASK 0x04u
+#define STATUS_PARITYERR_SHIFT 2u
+
+/*
+ * Overflow.
+ */
+#define STATUS_OVERFLOW_OFFSET 0x10u
+#define STATUS_OVERFLOW_MASK 0x08u
+#define STATUS_OVERFLOW_SHIFT 3u
+
+/*
+ * Frame Error.
+ */
+#define STATUS_FRAMERR_OFFSET 0x10u
+#define STATUS_FRAMERR_MASK 0x10u
+#define STATUS_FRAMERR_SHIFT 4u
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CORE_UART_APB_REGISTERS */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/cpu_types.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/cpu_types.h
new file mode 100644
index 000000000..1beae8c96
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/cpu_types.h
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#ifndef __CPU_TYPES_H
+#define __CPU_TYPES_H 1
+
+#include
+
+/*------------------------------------------------------------------------------
+ */
+typedef unsigned int size_t;
+
+/*------------------------------------------------------------------------------
+ * addr_t: address type.
+ * Used to specify the address of peripherals present in the processor's memory
+ * map.
+ */
+typedef unsigned int addr_t;
+
+/*------------------------------------------------------------------------------
+ * psr_t: processor state register.
+ * Used by HAL_disable_interrupts() and HAL_restore_interrupts() to store the
+ * processor's state between disabling and restoring interrupts.
+ */
+typedef unsigned int psr_t;
+
+#endif /* __CPU_TYPES_H */
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal.h
new file mode 100644
index 000000000..5b82ed07d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal.h
@@ -0,0 +1,207 @@
+/***************************************************************************//**
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Hardware abstraction layer functions.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#ifndef HAL_H_
+#define HAL_H_
+
+#include "cpu_types.h"
+#include "hw_reg_access.h"
+
+/***************************************************************************//**
+ * Enable all interrupts at the processor level.
+ */
+void HAL_enable_interrupts( void );
+
+/***************************************************************************//**
+ * Disable all interrupts at the processor core level.
+ * Return the interrupts enable state before disabling occured so that it can
+ * later be restored.
+ */
+psr_t HAL_disable_interrupts( void );
+
+/***************************************************************************//**
+ * Restore the interrupts enable state at the processor core level.
+ * This function is normally passed the value returned from a previous call to
+ * HAL_disable_interrupts().
+ */
+void HAL_restore_interrupts( psr_t saved_psr );
+
+/***************************************************************************//**
+ */
+#define FIELD_OFFSET(FIELD_NAME) (FIELD_NAME##_OFFSET)
+#define FIELD_SHIFT(FIELD_NAME) (FIELD_NAME##_SHIFT)
+#define FIELD_MASK(FIELD_NAME) (FIELD_NAME##_MASK)
+
+/***************************************************************************//**
+ * The macro HAL_set_32bit_reg() allows writing a 32 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint32_t containing the value to write.
+ */
+#define HAL_set_32bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_32bit_reg() is used to read the value of a 32 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint32_t value.
+ */
+#define HAL_get_32bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_32bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)) ))
+
+/***************************************************************************//**
+ * The macro HAL_set_32bit_reg_field() is used to write a field within a
+ * 32 bits wide register. The field written can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint32_t containing the field value to write.
+ */
+#define HAL_set_32bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_32bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_32bit_reg_field() is used to read a register field from
+ * within a 32 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint32_t value.
+ */
+#define HAL_get_32bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_32bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+/***************************************************************************//**
+ * The macro HAL_set_16bit_reg() allows writing a 16 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint_fast16_t containing the value to write.
+ */
+#define HAL_set_16bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_16bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_16bit_reg() is used to read the value of a 16 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint16_t value.
+ */
+#define HAL_get_16bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_16bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))
+
+/***************************************************************************//**
+ * The macro HAL_set_16bit_reg_field() is used to write a field within a
+ * 16 bits wide register. The field written can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint16_t containing the field value to write.
+ */
+#define HAL_set_16bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_16bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_16bit_reg_field() is used to read a register field from
+ * within a 8 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint16_t value.
+ */
+#define HAL_get_16bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_16bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+/***************************************************************************//**
+ * The macro HAL_set_8bit_reg() allows writing a 8 bits wide register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to write. These strings are
+ * specified in a header file associated with the peripheral.
+ * VALUE: A variable of type uint_fast8_t containing the value to write.
+ */
+#define HAL_set_8bit_reg(BASE_ADDR, REG_NAME, VALUE) \
+ (HW_set_8bit_reg( ((BASE_ADDR) + (REG_NAME##_REG_OFFSET)), (VALUE) ))
+
+/***************************************************************************//**
+ * The macro HAL_get_8bit_reg() is used to read the value of a 8 bits wide
+ * register.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * REG_NAME: A string identifying the register to read. These strings are
+ * specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint8_t value.
+ */
+#define HAL_get_8bit_reg(BASE_ADDR, REG_NAME) \
+ (HW_get_8bit_reg( (BASE_ADDR) + (REG_NAME##_REG_OFFSET) ))
+
+/***************************************************************************//**
+ */
+#define HAL_set_8bit_reg_field(BASE_ADDR, FIELD_NAME, VALUE) \
+ (HW_set_8bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME),\
+ (VALUE)))
+
+/***************************************************************************//**
+ * The macro HAL_get_8bit_reg_field() is used to read a register field from
+ * within a 8 bit wide peripheral register. The field can be one or more bits.
+ *
+ * BASE_ADDR: A variable of type addr_t specifying the base address of the
+ * peripheral containing the register.
+ * FIELD_NAME: A string identifying the register field to write. These strings
+ * are specified in a header file associated with the peripheral.
+ * RETURN: This function-like macro returns a uint8_t value.
+ */
+#define HAL_get_8bit_reg_field(BASE_ADDR, FIELD_NAME) \
+ (HW_get_8bit_reg_field(\
+ (BASE_ADDR) + FIELD_OFFSET(FIELD_NAME),\
+ FIELD_SHIFT(FIELD_NAME),\
+ FIELD_MASK(FIELD_NAME)))
+
+#endif /*HAL_H_*/
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_assert.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_assert.h
new file mode 100644
index 000000000..db8ab7703
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_assert.h
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * (c) Copyright 2008-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#ifndef HAL_ASSERT_HEADER
+#define HAL_ASSERT_HEADER
+
+#define NDEBUG 1
+
+#if defined(NDEBUG)
+/***************************************************************************//**
+ * HAL_ASSERT() is defined out when the NDEBUG symbol is used.
+ ******************************************************************************/
+#define HAL_ASSERT(CHECK)
+
+#else
+/***************************************************************************//**
+ * Default behaviour for HAL_ASSERT() macro:
+ *------------------------------------------------------------------------------
+ The behaviour is toolchain specific and project setting specific.
+ ******************************************************************************/
+#define HAL_ASSERT(CHECK) ASSERT(CHECK);
+
+#endif /* NDEBUG */
+
+#endif /* HAL_ASSERT_HEADER */
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_irq.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_irq.c
new file mode 100644
index 000000000..52f63016e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hal_irq.c
@@ -0,0 +1,36 @@
+/***************************************************************************//**
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Legacy interrupt control functions for the Microsemi driver library hardware
+ * abstraction layer.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#include "hal.h"
+#include "riscv_hal.h"
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void HAL_enable_interrupts(void) {
+ __enable_irq();
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+psr_t HAL_disable_interrupts(void) {
+ psr_t psr;
+ psr = read_csr(mstatus);
+ __disable_irq();
+ return(psr);
+}
+
+/*------------------------------------------------------------------------------
+ *
+ */
+void HAL_restore_interrupts(psr_t saved_psr) {
+ write_csr(mstatus, saved_psr);
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_macros.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_macros.h
new file mode 100644
index 000000000..2149544ca
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_macros.h
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Hardware registers access macros.
+ *
+ * THE MACROS DEFINED IN THIS FILE ARE DEPRECATED. DO NOT USED FOR NEW
+ * DEVELOPMENT.
+ *
+ * These macros are used to access peripheral's registers. They allow access to
+ * 8, 16 and 32 bit wide registers. All accesses to peripheral registers should
+ * be done through these macros in order to ease porting across different
+ * processors/bus architectures.
+ *
+ * Some of these macros also allow to access a specific register field.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#ifndef __HW_REGISTER_MACROS_H
+#define __HW_REGISTER_MACROS_H 1
+
+/*------------------------------------------------------------------------------
+ * 32 bits registers access:
+ */
+#define HW_get_uint32_reg(BASE_ADDR, REG_OFFSET) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint32_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint32_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint32_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint32_t) \
+ ( \
+ (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint32_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint32_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint32_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 32 bits memory access:
+ */
+#define HW_get_uint32(BASE_ADDR) (*((uint32_t volatile *)(BASE_ADDR)))
+
+#define HW_set_uint32(BASE_ADDR, VALUE) (*((uint32_t volatile *)(BASE_ADDR)) = (VALUE))
+
+/*------------------------------------------------------------------------------
+ * 16 bits registers access:
+ */
+#define HW_get_uint16_reg(BASE_ADDR, REG_OFFSET) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint16_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint16_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint16_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint16_t) \
+ ( \
+ (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint16_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint16_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint16_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 8 bits registers access:
+ */
+#define HW_get_uint8_reg(BASE_ADDR, REG_OFFSET) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)))
+
+#define HW_set_uint8_reg(BASE_ADDR, REG_OFFSET, VALUE) (*((uint8_t volatile *)(BASE_ADDR + REG_OFFSET##_REG_OFFSET)) = (VALUE))
+
+#define HW_set_uint8_reg_field(BASE_ADDR, FIELD, VALUE) \
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET)) = \
+ ( \
+ (uint8_t) \
+ ( \
+ (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & ~FIELD##_MASK) | \
+ (uint8_t)(((VALUE) << FIELD##_SHIFT) & FIELD##_MASK) \
+ ) \
+ )
+
+#define HW_get_uint8_reg_field( BASE_ADDR, FIELD ) \
+ (( (*((uint8_t volatile *)(BASE_ADDR + FIELD##_OFFSET))) & FIELD##_MASK) >> FIELD##_SHIFT)
+
+/*------------------------------------------------------------------------------
+ * 8 bits memory access:
+ */
+#define HW_get_uint8(BASE_ADDR) (*((uint8_t volatile *)(BASE_ADDR)))
+
+#define HW_set_uint8(BASE_ADDR, VALUE) (*((uint8_t volatile *)(BASE_ADDR)) = (VALUE))
+
+#endif /* __HW_REGISTER_MACROS_H */
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.S b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.S
new file mode 100644
index 000000000..68d93dd4c
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.S
@@ -0,0 +1,209 @@
+/***************************************************************************//**
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Hardware registers access functions.
+ * The implementation of these function is platform and toolchain specific.
+ * The functions declared here are implemented using assembler as part of the
+ * processor/toolchain specific HAL.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+
+.section .text
+ .globl HW_set_32bit_reg
+ .globl HW_get_32bit_reg
+ .globl HW_set_32bit_reg_field
+ .globl HW_get_32bit_reg_field
+ .globl HW_set_16bit_reg
+ .globl HW_get_16bit_reg
+ .globl HW_set_16bit_reg_field
+ .globl HW_get_16bit_reg_field
+ .globl HW_set_8bit_reg
+ .globl HW_get_8bit_reg
+ .globl HW_set_8bit_reg_field
+ .globl HW_get_8bit_reg_field
+
+
+/***************************************************************************//**
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint32_t value
+ */
+HW_set_32bit_reg:
+ sw a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral
+ * register.
+ *
+ * R0: addr_t reg_addr
+ * @return 32 bits value read from the peripheral register.
+ */
+HW_get_32bit_reg:
+ lw a0, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint32_t mask
+ * a3: uint32_t value
+ */
+HW_set_32bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lw t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sw t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_32bit_reg_field is used to read the content of a field out of a
+ * 32 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint32_t mask
+ *
+ * @return 32 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_32bit_reg_field:
+ lw a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+/***************************************************************************//**
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint_fast16_t value
+ */
+HW_set_16bit_reg:
+ sh a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * @return 16 bits value read from the peripheral register.
+ */
+HW_get_16bit_reg:
+ lh a0, (a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast16_t mask
+ * a3: uint_fast16_t value
+ * @param value Value to be written in the specified field.
+ */
+HW_set_16bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lh t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sh t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_16bit_reg_field is used to read the content of a field from a
+ * 16 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast16_t mask
+ *
+ * @return 16 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_16bit_reg_field:
+ lh a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+/***************************************************************************//**
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * a1: uint_fast8_t value
+ */
+HW_set_8bit_reg:
+ sb a1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral
+ * register.
+ *
+ * a0: addr_t reg_addr
+ * @return 8 bits value read from the peripheral register.
+ */
+HW_get_8bit_reg:
+ lb a0, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits
+ * wide peripheral register.
+ *
+ * a0: addr_t reg_addr,
+ * a1: int_fast8_t shift
+ * a2: uint_fast8_t mask
+ * a3: uint_fast8_t value
+ */
+HW_set_8bit_reg_field:
+ mv t3, a3
+ sll t3, t3, a1
+ and t3, t3, a2
+ lb t1, 0(a0)
+ mv t2, a2
+ not t2, t2
+ and t1, t1, t2
+ or t1, t1, t3
+ sb t1, 0(a0)
+ ret
+
+/***************************************************************************//**
+ * HW_get_8bit_reg_field is used to read the content of a field from a
+ * 8 bits wide peripheral register.
+ *
+ * a0: addr_t reg_addr
+ * a1: int_fast8_t shift
+ * a2: uint_fast8_t mask
+ *
+ * @return 8 bits value containing the register field value specified
+ * as parameter.
+ */
+HW_get_8bit_reg_field:
+ lb a0, 0(a0)
+ and a0, a0, a2
+ srl a0, a0, a1
+ ret
+
+.end
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.h
new file mode 100644
index 000000000..bc3dd654a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hal/hw_reg_access.h
@@ -0,0 +1,229 @@
+/***************************************************************************//**
+ * (c) Copyright 2007-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * Hardware registers access functions.
+ * The implementation of these function is platform and toolchain specific.
+ * The functions declared here are implemented using assembler as part of the
+ * processor/toolchain specific HAL.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#ifndef HW_REG_ACCESS
+#define HW_REG_ACCESS
+
+#include "cpu_types.h"
+/***************************************************************************//**
+ * HW_set_32bit_reg is used to write the content of a 32 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_32bit_reg
+(
+ addr_t reg_addr,
+ uint32_t value
+);
+
+/***************************************************************************//**
+ * HW_get_32bit_reg is used to read the content of a 32 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 32 bits value read from the peripheral register.
+ */
+uint32_t
+HW_get_32bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_32bit_reg_field is used to set the content of a field in a 32 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void
+HW_set_32bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint32_t mask,
+ uint32_t value
+);
+
+/***************************************************************************//**
+ * HW_get_32bit_reg_field is used to read the content of a field out of a
+ * 32 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 32 bits value containing the register field value specified
+ * as parameter.
+ */
+uint32_t
+HW_get_32bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint32_t mask
+);
+
+/***************************************************************************//**
+ * HW_set_16bit_reg is used to write the content of a 16 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_16bit_reg
+(
+ addr_t reg_addr,
+ uint_fast16_t value
+);
+
+/***************************************************************************//**
+ * HW_get_16bit_reg is used to read the content of a 16 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 16 bits value read from the peripheral register.
+ */
+uint16_t
+HW_get_16bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_16bit_reg_field is used to set the content of a field in a 16 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void HW_set_16bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast16_t mask,
+ uint_fast16_t value
+);
+
+/***************************************************************************//**
+ * HW_get_16bit_reg_field is used to read the content of a field from a
+ * 16 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 16 bits value containing the register field value specified
+ * as parameter.
+ */
+uint16_t HW_get_16bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast16_t mask
+);
+
+/***************************************************************************//**
+ * HW_set_8bit_reg is used to write the content of a 8 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * write.
+ * @param value Value to be written into the peripheral register.
+ */
+void
+HW_set_8bit_reg
+(
+ addr_t reg_addr,
+ uint_fast8_t value
+);
+
+/***************************************************************************//**
+ * HW_get_8bit_reg is used to read the content of a 8 bits wide peripheral
+ * register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @return 8 bits value read from the peripheral register.
+ */
+uint8_t
+HW_get_8bit_reg
+(
+ addr_t reg_addr
+);
+
+/***************************************************************************//**
+ * HW_set_8bit_reg_field is used to set the content of a field in a 8 bits
+ * wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * be written.
+ * @param shift Bit offset of the register field to be read within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ * @param value Value to be written in the specified field.
+ */
+void HW_set_8bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast8_t mask,
+ uint_fast8_t value
+);
+
+/***************************************************************************//**
+ * HW_get_8bit_reg_field is used to read the content of a field from a
+ * 8 bits wide peripheral register.
+ *
+ * @param reg_addr Address in the processor's memory map of the register to
+ * read.
+ * @param shift Bit offset of the register field to be written within the
+ * register.
+ * @param mask Bit mask to be applied to the raw register value to filter
+ * out the other register fields values.
+ *
+ * @return 8 bits value containing the register field value specified
+ * as parameter.
+ */
+uint8_t HW_get_8bit_reg_field
+(
+ addr_t reg_addr,
+ int_fast8_t shift,
+ uint_fast8_t mask
+);
+
+#endif /* HW_REG_ACCESS */
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h
new file mode 100644
index 000000000..268eba61f
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2017 Microsemi Corporation. All rights reserved.
+ *
+ * Platform definitions
+ * Version based on requirements of RISCV-HAL
+ *
+ * SVN $Revision: 9587 $
+ * SVN $Date: 2017-11-16 12:53:31 +0530 (Thu, 16 Nov 2017) $
+ */
+ /*=========================================================================*//**
+ @mainpage Sample file detailing how hw_platform.h should be constructed for
+ the Mi-V processors.
+
+ @section intro_sec Introduction
+ The hw_platform.h is to be located in the project root directory.
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.
+
+ You can use this file as sample.
+ Rename this file from sample_hw_platform.h to hw_platform.h and store it in
+ the root folder of your project. Then customize it per your HW design.
+
+ @section driver_configuration Project configuration Instructions
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock
+ 2 Add all other core BASE addresses
+ 3. Add peripheral Core Interrupt to Mi-V Soft processor interrupt mappings
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to STDIO
+*//*=========================================================================*/
+
+#ifndef HW_PLATFORM_H
+#define HW_PLATFORM_H
+
+/***************************************************************************//**
+ * Soft-processor clock definition
+ * This is the only clock brought over from the Mi-V Soft processor Libero design.
+ */
+#ifndef SYS_CLK_FREQ
+#define SYS_CLK_FREQ 83000000UL
+#endif
+
+/***************************************************************************//**
+ * Non-memory Peripheral base addresses
+ * Format of define is:
+ * __BASE_ADDR
+ */
+#define COREUARTAPB0_BASE_ADDR 0x70001000UL
+#define COREGPIO_IN_BASE_ADDR 0x70002000UL
+#define CORETIMER0_BASE_ADDR 0x70003000UL
+#define CORETIMER1_BASE_ADDR 0x70004000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70005000UL
+#define FLASH_CORE_SPI_BASE 0x70006000UL
+#define CORE16550_BASE_ADDR 0x70007000UL
+
+/***************************************************************************//**
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor
+ * interrupt from the Libero design.
+ * There can be up to 31 external interrupts (IRQ[30:0] pins) on the Mi-V Soft
+ * processor.The Mi-V Soft processor external interrupts are defined in the
+ * riscv_plic.h
+ * These are of the form
+ * typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ .
+ .
+ .
+ External_31_IRQn = 31
+} IRQn_Type;
+
+ The interrupt 0 on RISC-V processor is not used. The pin IRQ[0] should map to
+ External_1_IRQn likewise IRQ[30] should map to External_31_IRQn
+ * Format of define is:
+ * __
+ */
+
+#define TIMER0_IRQn External_30_IRQn
+#define TIMER1_IRQn External_31_IRQn
+
+/****************************************************************************
+ * Baud value to achieve a 115200 baud rate with a 83MHz system clock.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+#define BAUD_VALUE_115200 (SYS_CLK_FREQ / (16 * 115200)) - 1
+
+/***************************************************************************//**
+ * User edit section- Edit sections below if required
+ */
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+/*
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb
+ * must be provided if it is being used
+ *
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+ */
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR
+
+#ifndef MSCC_STDIO_UART_BASE_ADDR
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+#endif
+
+#ifndef MSCC_STDIO_BAUD_VALUE
+/*
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to
+ * specify the baud value used by the standard output CoreUARTapb instance for
+ * generating the UART's baud rate if you want a different baud rate from the
+ * default of 115200 baud
+ */
+#define MSCC_STDIO_BAUD_VALUE 115200
+#endif /*MSCC_STDIO_BAUD_VALUE*/
+
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */
+/*******************************************************************************
+ * End of user edit section
+ */
+#endif /* HW_PLATFORM_H */
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/main.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/main.c
new file mode 100644
index 000000000..4ec3a71ad
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/main.c
@@ -0,0 +1,136 @@
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "timers.h"
+
+#include "hw_platform.h"
+#include "core_uart_apb.h"
+#include "task.h"
+
+const char * g_hello_msg = "\r\nFreeRTOS Example\r\n";
+
+
+/* A block time of zero simply means "don't block". */
+#define mainDONT_BLOCK ( 0UL )
+
+/******************************************************************************
+ * CoreUARTapb instance data.
+ *****************************************************************************/
+UART_instance_t g_uart;
+/*-----------------------------------------------------------*/
+
+static void vUartTestTask1( void *pvParameters );
+static void vUartTestTask2( void *pvParameters );
+
+/*
+ * FreeRTOS hook for when malloc fails, enable in FreeRTOSConfig.
+ */
+void vApplicationMallocFailedHook( void );
+
+/*
+ * FreeRTOS hook for when FreeRtos is idling, enable in FreeRTOSConfig.
+ */
+void vApplicationIdleHook( void );
+
+/*
+ * FreeRTOS hook for when a stack overflow occurs, enable in FreeRTOSConfig.
+ */
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );
+
+/*-----------------------------------------------------------*/
+
+int main( void )
+{
+ PLIC_init();
+
+ /**************************************************************************
+ * Initialize CoreUART with its base address, baud value, and line
+ * configuration.
+ *************************************************************************/
+ UART_init(&g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200,
+ (DATA_8_BITS | NO_PARITY) );
+
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"\r\n\r\n Sample Demonstration of FreeRTOS port for Mi-V processor.\r\n\r\n" );
+ UART_polled_tx_string( &g_uart, (const uint8_t *)" This project creates two tasks and runs them at regular intervals.\r\n" );
+
+ /* Create the two test tasks. */
+ xTaskCreate( vUartTestTask1, "UArt1", 1000, NULL, uartPRIMARY_PRIORITY, NULL );
+ xTaskCreate( vUartTestTask2, "UArt2", 1000, NULL, uartPRIMARY_PRIORITY, NULL );
+
+ /* Start the kernel. From here on, only tasks and interrupts will run. */
+ vTaskStartScheduler();
+
+ /* Exit FreeRTOS */
+ return 0;
+}
+
+/*-----------------------------------------------------------*/
+
+void vApplicationMallocFailedHook( void )
+{
+ /* vApplicationMallocFailedHook() will only be called if
+ configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
+ function that will get called if a call to pvPortMalloc() fails.
+ pvPortMalloc() is called internally by the kernel whenever a task, queue,
+ timer or semaphore is created. It is also called by various parts of the
+ demo application. If heap_1.c or heap_2.c are used, then the size of the
+ heap available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
+ FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
+ to query the size of free heap space that remains (although it does not
+ provide information on how the remaining heap might be fragmented). */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationIdleHook( void )
+{
+ /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
+ to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
+ task. It is essential that code added to this hook function never attempts
+ to block in any way (for example, call xQueueReceive() with a block time
+ specified, or call vTaskDelay()). If the application makes use of the
+ vTaskDelete() API function (as this demo application does) then it is also
+ important that vApplicationIdleHook() is permitted to return to its calling
+ function, because it is the responsibility of the idle task to clean up
+ memory allocated by the kernel to any task that has since been deleted. */
+}
+/*-----------------------------------------------------------*/
+
+void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
+{
+ ( void ) pcTaskName;
+ ( void ) pxTask;
+
+ /* Run time stack overflow checking is performed if
+ configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
+ function is called if a stack overflow is detected. */
+ taskDISABLE_INTERRUPTS();
+ for( ;; );
+}
+/*-----------------------------------------------------------*/
+
+static void vUartTestTask1( void *pvParameters )
+{
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"Task - 1\r\n" );
+ vTaskDelay(10);
+ }
+}
+
+
+/*-----------------------------------------------------------*/
+
+static void vUartTestTask2( void *pvParameters )
+{
+ ( void ) pvParameters;
+
+ for( ;; )
+ {
+ UART_polled_tx_string( &g_uart, (const uint8_t *)"Task - 2\r\n" );
+ vTaskDelay(5);
+ }
+}
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/encoding.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/encoding.h
new file mode 100644
index 000000000..aa379ee5a
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/encoding.h
@@ -0,0 +1,596 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file encodings.h
+ * @author Microsemi SoC Products Group
+ * @brief Mi-V soft processor register bit mask and shift constants encodings.
+ *
+ * SVN $Revision: 9825 $
+ * SVN $Date: 2018-03-19 10:31:41 +0530 (Mon, 19 Mar 2018) $
+ */
+#ifndef RISCV_CSR_ENCODING_H
+#define RISCV_CSR_ENCODING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MSTATUS_UIE 0x00000001
+#define MSTATUS_SIE 0x00000002
+#define MSTATUS_HIE 0x00000004
+#define MSTATUS_MIE 0x00000008
+#define MSTATUS_UPIE 0x00000010
+#define MSTATUS_SPIE 0x00000020
+#define MSTATUS_HPIE 0x00000040
+#define MSTATUS_MPIE 0x00000080
+#define MSTATUS_SPP 0x00000100
+#define MSTATUS_HPP 0x00000600
+#define MSTATUS_MPP 0x00001800
+#define MSTATUS_FS 0x00006000
+#define MSTATUS_XS 0x00018000
+#define MSTATUS_MPRV 0x00020000
+#define MSTATUS_SUM 0x00040000 /*changed in v1.10*/
+#define MSTATUS_MXR 0x00080000 /*changed in v1.10*/
+#define MSTATUS_TVM 0x00100000 /*changed in v1.10*/
+#define MSTATUS_TW 0x00200000 /*changed in v1.10*/
+#define MSTATUS_TSR 0x00400000 /*changed in v1.10*/
+#define MSTATUS_RES 0x7F800000 /*changed in v1.10*/
+#define MSTATUS32_SD 0x80000000
+#define MSTATUS64_SD 0x8000000000000000
+
+#define MCAUSE32_CAUSE 0x7FFFFFFF
+#define MCAUSE64_CAUSE 0x7FFFFFFFFFFFFFFF
+#define MCAUSE32_INT 0x80000000
+#define MCAUSE64_INT 0x8000000000000000
+
+#define SSTATUS_UIE 0x00000001
+#define SSTATUS_SIE 0x00000002
+#define SSTATUS_UPIE 0x00000010
+#define SSTATUS_SPIE 0x00000020
+#define SSTATUS_SPP 0x00000100
+#define SSTATUS_FS 0x00006000
+#define SSTATUS_XS 0x00018000
+#define SSTATUS_PUM 0x00040000
+#define SSTATUS32_SD 0x80000000
+#define SSTATUS64_SD 0x8000000000000000
+
+#define MIP_SSIP (1u << IRQ_S_SOFT)
+#define MIP_HSIP (1u << IRQ_H_SOFT)
+#define MIP_MSIP (1u << IRQ_M_SOFT)
+#define MIP_STIP (1u << IRQ_S_TIMER)
+#define MIP_HTIP (1u << IRQ_H_TIMER)
+#define MIP_MTIP (1u << IRQ_M_TIMER)
+#define MIP_SEIP (1u << IRQ_S_EXT)
+#define MIP_HEIP (1u << IRQ_H_EXT)
+#define MIP_MEIP (1u << IRQ_M_EXT)
+
+#define SIP_SSIP MIP_SSIP
+#define SIP_STIP MIP_STIP
+
+#define PRV_U 0
+#define PRV_S 1
+#define PRV_H 2
+#define PRV_M 3
+
+#define VM_MBARE 0
+#define VM_MBB 1
+#define VM_MBBID 2
+#define VM_SV32 8
+#define VM_SV39 9
+#define VM_SV48 10
+
+#define IRQ_S_SOFT 1
+#define IRQ_H_SOFT 2
+#define IRQ_M_SOFT 3
+#define IRQ_S_TIMER 5
+#define IRQ_H_TIMER 6
+#define IRQ_M_TIMER 7
+#define IRQ_S_EXT 9
+#define IRQ_H_EXT 10
+#define IRQ_M_EXT 11
+
+#define DEFAULT_RSTVEC 0x00001000
+#define DEFAULT_NMIVEC 0x00001004
+#define DEFAULT_MTVEC 0x00001010
+#define CONFIG_STRING_ADDR 0x0000100C
+#define EXT_IO_BASE 0x40000000
+#define DRAM_BASE 0x80000000
+
+/* page table entry (PTE) fields */
+#define PTE_V 0x001 /* Valid */
+#define PTE_TYPE 0x01E /* Type */
+#define PTE_R 0x020 /* Referenced */
+#define PTE_D 0x040 /* Dirty */
+#define PTE_SOFT 0x380 /* Reserved for Software */
+
+#define PTE_TYPE_TABLE 0x00
+#define PTE_TYPE_TABLE_GLOBAL 0x02
+#define PTE_TYPE_URX_SR 0x04
+#define PTE_TYPE_URWX_SRW 0x06
+#define PTE_TYPE_UR_SR 0x08
+#define PTE_TYPE_URW_SRW 0x0A
+#define PTE_TYPE_URX_SRX 0x0C
+#define PTE_TYPE_URWX_SRWX 0x0E
+#define PTE_TYPE_SR 0x10
+#define PTE_TYPE_SRW 0x12
+#define PTE_TYPE_SRX 0x14
+#define PTE_TYPE_SRWX 0x16
+#define PTE_TYPE_SR_GLOBAL 0x18
+#define PTE_TYPE_SRW_GLOBAL 0x1A
+#define PTE_TYPE_SRX_GLOBAL 0x1C
+#define PTE_TYPE_SRWX_GLOBAL 0x1E
+
+#define PTE_PPN_SHIFT 10
+
+#define PTE_TABLE(PTE) ((0x0000000AU >> ((PTE) & 0x1F)) & 1)
+#define PTE_UR(PTE) ((0x0000AAA0U >> ((PTE) & 0x1F)) & 1)
+#define PTE_UW(PTE) ((0x00008880U >> ((PTE) & 0x1F)) & 1)
+#define PTE_UX(PTE) ((0x0000A0A0U >> ((PTE) & 0x1F)) & 1)
+#define PTE_SR(PTE) ((0xAAAAAAA0U >> ((PTE) & 0x1F)) & 1)
+#define PTE_SW(PTE) ((0x88888880U >> ((PTE) & 0x1F)) & 1)
+#define PTE_SX(PTE) ((0xA0A0A000U >> ((PTE) & 0x1F)) & 1)
+
+#define PTE_CHECK_PERM(PTE, SUPERVISOR, STORE, FETCH) \
+ ((STORE) ? ((SUPERVISOR) ? PTE_SW(PTE) : PTE_UW(PTE)) : \
+ (FETCH) ? ((SUPERVISOR) ? PTE_SX(PTE) : PTE_UX(PTE)) : \
+ ((SUPERVISOR) ? PTE_SR(PTE) : PTE_UR(PTE)))
+
+#ifdef __riscv
+
+#if __riscv_xlen == 64
+# define MSTATUS_SD MSTATUS64_SD
+# define SSTATUS_SD SSTATUS64_SD
+# define MCAUSE_INT MCAUSE64_INT
+# define MCAUSE_CAUSE MCAUSE64_CAUSE
+# define RISCV_PGLEVEL_BITS 9
+#else
+# define MSTATUS_SD MSTATUS32_SD
+# define SSTATUS_SD SSTATUS32_SD
+# define RISCV_PGLEVEL_BITS 10
+# define MCAUSE_INT MCAUSE32_INT
+# define MCAUSE_CAUSE MCAUSE32_CAUSE
+#endif
+
+#define RISCV_PGSHIFT 12
+#define RISCV_PGSIZE (1 << RISCV_PGSHIFT)
+
+#ifndef __ASSEMBLER__
+
+#ifdef __GNUC__
+
+#define read_csr(reg) ({ unsigned long __tmp; \
+ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
+ __tmp; })
+
+#define write_csr(reg, val) ({ \
+ if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
+ asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
+ else \
+ asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
+
+#define swap_csr(reg, val) ({ unsigned long __tmp; \
+ if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
+ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \
+ else \
+ asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \
+ __tmp; })
+
+#define set_csr(reg, bit) ({ unsigned long __tmp; \
+ if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
+ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+ else \
+ asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+ __tmp; })
+
+#define clear_csr(reg, bit) ({ unsigned long __tmp; \
+ if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
+ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \
+ else \
+ asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \
+ __tmp; })
+
+#define rdtime() read_csr(time)
+#define rdcycle() read_csr(cycle)
+#define rdinstret() read_csr(instret)
+
+#ifdef __riscv_atomic
+
+#define MASK(nr) (1UL << nr)
+#define MASK_NOT(nr) (~(1UL << nr))
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically reads the value of @v.
+ */
+static inline int atomic_read(const int *v)
+{
+ return *((volatile int *)(v));
+}
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type int
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+static inline void atomic_set(int *v, int i)
+{
+ *v = i;
+}
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v.
+ */
+static inline void atomic_add(int i, int *v)
+{
+ __asm__ __volatile__ (
+ "amoadd.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (i));
+}
+
+static inline int atomic_fetch_add(unsigned int mask, int *v)
+{
+ int out;
+
+ __asm__ __volatile__ (
+ "amoadd.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_sub - subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v.
+ */
+static inline void atomic_sub(int i, int *v)
+{
+ atomic_add(-i, v);
+}
+
+static inline int atomic_fetch_sub(unsigned int mask, int *v)
+{
+ int out;
+
+ __asm__ __volatile__ (
+ "amosub.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_add_return - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v and returns the result
+ */
+static inline int atomic_add_return(int i, int *v)
+{
+ register int c;
+ __asm__ __volatile__ (
+ "amoadd.w %0, %2, %1"
+ : "=r" (c), "+A" (*v)
+ : "r" (i));
+ return (c + i);
+}
+
+/**
+ * atomic_sub_return - subtract integer from atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v and returns the result
+ */
+static inline int atomic_sub_return(int i, int *v)
+{
+ return atomic_add_return(-i, v);
+}
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically increments @v by 1.
+ */
+static inline void atomic_inc(int *v)
+{
+ atomic_add(1, v);
+}
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type int
+ *
+ * Atomically decrements @v by 1.
+ */
+static inline void atomic_dec(int *v)
+{
+ atomic_add(-1, v);
+}
+
+static inline int atomic_inc_return(int *v)
+{
+ return atomic_add_return(1, v);
+}
+
+static inline int atomic_dec_return(int *v)
+{
+ return atomic_sub_return(1, v);
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type int
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_sub_and_test(int i, int *v)
+{
+ return (atomic_sub_return(i, v) == 0);
+}
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type int
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_inc_and_test(int *v)
+{
+ return (atomic_inc_return(v) == 0);
+}
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type int
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline int atomic_dec_and_test(int *v)
+{
+ return (atomic_dec_return(v) == 0);
+}
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @i: integer value to add
+ * @v: pointer of type int
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static inline int atomic_add_negative(int i, int *v)
+{
+ return (atomic_add_return(i, v) < 0);
+}
+
+static inline int atomic_xchg(int *v, int n)
+{
+ register int c;
+ __asm__ __volatile__ (
+ "amoswap.w %0, %2, %1"
+ : "=r" (c), "+A" (*v)
+ : "r" (n));
+ return c;
+}
+
+/**
+ * atomic_and - Atomically clear bits in atomic variable
+ * @mask: Mask of the bits to be retained
+ * @v: pointer of type int
+ *
+ * Atomically retains the bits set in @mask from @v
+ */
+static inline void atomic_and(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoand.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_and(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoand.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_or - Atomically set bits in atomic variable
+ * @mask: Mask of the bits to be set
+ * @v: pointer of type int
+ *
+ * Atomically sets the bits set in @mask in @v
+ */
+static inline void atomic_or(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoor.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_or(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoor.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/**
+ * atomic_xor - Atomically flips bits in atomic variable
+ * @mask: Mask of the bits to be flipped
+ * @v: pointer of type int
+ *
+ * Atomically flips the bits set in @mask in @v
+ */
+static inline void atomic_xor(unsigned int mask, int *v)
+{
+ __asm__ __volatile__ (
+ "amoxor.w zero, %1, %0"
+ : "+A" (*v)
+ : "r" (mask));
+}
+
+static inline int atomic_fetch_xor(unsigned int mask, int *v)
+{
+ int out;
+ __asm__ __volatile__ (
+ "amoxor.w %2, %1, %0"
+ : "+A" (*v), "=r" (out)
+ : "r" (mask));
+ return out;
+}
+
+/*----------------------------------------------------*/
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long __res, __mask;
+ __mask = MASK(nr);
+ __asm__ __volatile__ ( \
+ "amoor.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long __res, __mask;
+ __mask = MASK_NOT(nr);
+ __asm__ __volatile__ ( \
+ "amoand.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its old value
+ * @nr: Bit to change
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
+{
+
+ unsigned long __res, __mask;
+ __mask = MASK(nr);
+ __asm__ __volatile__ ( \
+ "amoxor.w %0, %2, %1" \
+ : "=r" (__res), "+A" (*addr) \
+ : "r" (__mask)); \
+
+ return ((__res & __mask) != 0);
+}
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered.
+ */
+
+static inline void set_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOOR.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK(nr)));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered.
+ */
+static inline void clear_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOAND.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK_NOT(nr)));
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ */
+static inline void change_bit(int nr, volatile unsigned long *addr)
+{
+ __asm__ __volatile__ ( \
+ "AMOXOR.w zero, %1, %0" \
+ : "+A" (*addr) \
+ : "r" (MASK(nr)));
+}
+
+#endif /* __riscv_atomic */
+
+#endif /*__GNUC__*/
+
+#endif /*__ASSEMBLER__*/
+
+#endif /*__riscv*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*RISCV_CSR_ENCODING_H*/
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/entry.S b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/entry.S
new file mode 100644
index 000000000..6e3ef92a7
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/entry.S
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file entry.S
+ * @author Microsemi SoC Products Group
+ * @brief Mi-V soft processor vectors, trap handling and startup code.
+ *
+ * SVN $Revision: 9947 $
+ * SVN $Date: 2018-04-30 20:28:49 +0530 (Mon, 30 Apr 2018) $
+ */
+#ifndef ENTRY_S
+#define ENTRY_S
+
+#include "encoding.h"
+
+#if __riscv_xlen == 64
+# define LREG ld
+# define SREG sd
+# define REGBYTES 8
+#else
+# define LREG lw
+# define SREG sw
+# define REGBYTES 4
+#endif
+
+ .section .text.entry
+ .globl _start
+
+_start:
+ j handle_reset
+
+nmi_vector:
+ j nmi_vector
+
+trap_vector:
+ j trap_entry
+
+handle_reset:
+ la t0, trap_entry
+ csrw mtvec, t0
+ csrwi mstatus, 0
+ csrwi mie, 0
+
+/*Floating point support configuration*/
+
+#ifdef __riscv_flen
+ csrr t0, mstatus
+ lui t1, 0xffffa
+ addi t1, t1, -1
+ and t0, t0, t1
+ lui t1, 0x4
+ or t1, t0, t1
+ csrw mstatus, t1
+
+ lui t0, 0x0
+ fscsr t0
+#endif
+.option push
+
+# Ensure the instruction is not optimized, since gp is not yet set
+
+.option norelax
+ # initialize global pointer
+ la gp, __global_pointer$
+
+.option pop
+
+ # initialize stack pointer
+ la sp, __stack_top
+
+ # perform the rest of initialization in C
+ j _init
+
+
+trap_entry:
+ addi sp, sp, -32*REGBYTES
+
+ SREG x1, 0 * REGBYTES(sp)
+ SREG x2, 1 * REGBYTES(sp)
+ SREG x3, 2 * REGBYTES(sp)
+ SREG x4, 3 * REGBYTES(sp)
+ SREG x5, 4 * REGBYTES(sp)
+ SREG x6, 5 * REGBYTES(sp)
+ SREG x7, 6 * REGBYTES(sp)
+ SREG x8, 7 * REGBYTES(sp)
+ SREG x9, 8 * REGBYTES(sp)
+ SREG x10, 9 * REGBYTES(sp)
+ SREG x11, 10 * REGBYTES(sp)
+ SREG x12, 11 * REGBYTES(sp)
+ SREG x13, 12 * REGBYTES(sp)
+ SREG x14, 13 * REGBYTES(sp)
+ SREG x15, 14 * REGBYTES(sp)
+ SREG x16, 15 * REGBYTES(sp)
+ SREG x17, 16 * REGBYTES(sp)
+ SREG x18, 17 * REGBYTES(sp)
+ SREG x19, 18 * REGBYTES(sp)
+ SREG x20, 19 * REGBYTES(sp)
+ SREG x21, 20 * REGBYTES(sp)
+ SREG x22, 21 * REGBYTES(sp)
+ SREG x23, 22 * REGBYTES(sp)
+ SREG x24, 23 * REGBYTES(sp)
+ SREG x25, 24 * REGBYTES(sp)
+ SREG x26, 25 * REGBYTES(sp)
+ SREG x27, 26 * REGBYTES(sp)
+ SREG x28, 27 * REGBYTES(sp)
+ SREG x29, 28 * REGBYTES(sp)
+ SREG x30, 29 * REGBYTES(sp)
+ SREG x31, 30 * REGBYTES(sp)
+
+
+ csrr t0, mepc
+ SREG t0, 31 * REGBYTES(sp)
+
+ csrr a0, mcause
+ csrr a1, mepc
+ mv a2, sp
+ jal handle_trap
+ csrw mepc, a0
+
+ # Remain in M-mode after mret
+ li t0, MSTATUS_MPP
+ csrs mstatus, t0
+
+ LREG x1, 0 * REGBYTES(sp)
+ LREG x2, 1 * REGBYTES(sp)
+ LREG x3, 2 * REGBYTES(sp)
+ LREG x4, 3 * REGBYTES(sp)
+ LREG x5, 4 * REGBYTES(sp)
+ LREG x6, 5 * REGBYTES(sp)
+ LREG x7, 6 * REGBYTES(sp)
+ LREG x8, 7 * REGBYTES(sp)
+ LREG x9, 8 * REGBYTES(sp)
+ LREG x10, 9 * REGBYTES(sp)
+ LREG x11, 10 * REGBYTES(sp)
+ LREG x12, 11 * REGBYTES(sp)
+ LREG x13, 12 * REGBYTES(sp)
+ LREG x14, 13 * REGBYTES(sp)
+ LREG x15, 14 * REGBYTES(sp)
+ LREG x16, 15 * REGBYTES(sp)
+ LREG x17, 16 * REGBYTES(sp)
+ LREG x18, 17 * REGBYTES(sp)
+ LREG x19, 18 * REGBYTES(sp)
+ LREG x20, 19 * REGBYTES(sp)
+ LREG x21, 20 * REGBYTES(sp)
+ LREG x22, 21 * REGBYTES(sp)
+ LREG x23, 22 * REGBYTES(sp)
+ LREG x24, 23 * REGBYTES(sp)
+ LREG x25, 24 * REGBYTES(sp)
+ LREG x26, 25 * REGBYTES(sp)
+ LREG x27, 26 * REGBYTES(sp)
+ LREG x28, 27 * REGBYTES(sp)
+ LREG x29, 28 * REGBYTES(sp)
+ LREG x30, 29 * REGBYTES(sp)
+ LREG x31, 30 * REGBYTES(sp)
+
+ addi sp, sp, 32*REGBYTES
+ mret
+
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/init.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/init.c
new file mode 100644
index 000000000..8c5998f4d
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/init.c
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file init.c
+ * @author Microsemi SoC Products Group
+ * @brief Mi-V soft processor memory section initializations and start-up code.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+
+#include
+#include
+#include
+
+#include "encoding.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t __sdata_load;
+extern uint32_t __sdata_start;
+extern uint32_t __sdata_end;
+
+extern uint32_t __data_load;
+extern uint32_t __data_start;
+extern uint32_t __data_end;
+
+extern uint32_t __sbss_start;
+extern uint32_t __sbss_end;
+extern uint32_t __bss_start;
+extern uint32_t __bss_end;
+
+
+static void copy_section(uint32_t * p_load, uint32_t * p_vma, uint32_t * p_vma_end)
+{
+ while(p_vma <= p_vma_end)
+ {
+ *p_vma = *p_load;
+ ++p_load;
+ ++p_vma;
+ }
+}
+
+static void zero_section(uint32_t * start, uint32_t * end)
+{
+ uint32_t * p_zero = start;
+
+ while(p_zero <= end)
+ {
+ *p_zero = 0;
+ ++p_zero;
+ }
+}
+
+void _init(void)
+{
+ extern int main(int, char**);
+ const char *argv0 = "hello";
+ char *argv[] = {(char *)argv0, NULL, NULL};
+
+ copy_section(&__sdata_load, &__sdata_start, &__sdata_end);
+ copy_section(&__data_load, &__data_start, &__data_end);
+ zero_section(&__sbss_start, &__sbss_end);
+ zero_section(&__bss_start, &__bss_end);
+
+ main(1, argv);
+}
+
+/* Function called after main() finishes */
+void
+_fini()
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-igloo2.ld b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-igloo2.ld
new file mode 100644
index 000000000..11d069715
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-igloo2.ld
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * file name : microsemi-riscv-igloo2.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * image executing in eNVM.
+ *
+ * This linker script assumes that the eNVM is connected at on the Mi-V soft
+ * processor memory space.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+
+MEMORY
+{
+ envm (rx) : ORIGIN = 0x60000000, LENGTH = 240k
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 64k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 64k; /* Must be the same value MEMORY region ram LENGTH above. */
+STACK_SIZE = 2k; /* needs to be calculated for your application */
+HEAP_SIZE = 2k; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .text : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.text.entry)))
+ . = ALIGN(0x10);
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } >envm
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } >ram AT>envm
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } >ram AT>envm
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-ram.ld b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-ram.ld
new file mode 100644
index 000000000..d63709e68
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/microsemi-riscv-ram.ld
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * file name : microsemi-riscv-ram.ld
+ * Mi-V soft processor linker script for creating a SoftConsole downloadable
+ * debug image executing in SRAM.
+ *
+ * This linker script assumes that the SRAM is connected at on the Mi-V soft
+ * processor memory space. The start address and size of the memory space must
+ * be correct as per the Libero design.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+
+MEMORY
+{
+ ram (rwx) : ORIGIN = 0x80000000, LENGTH = 512k
+}
+
+RAM_START_ADDRESS = 0x80000000; /* Must be the same value MEMORY region ram ORIGIN above. */
+RAM_SIZE = 512k; /* Must be the same value MEMORY region ram LENGTH above. */
+STACK_SIZE = 64k; /* needs to be calculated for your application */
+HEAP_SIZE = 64k; /* needs to be calculated for your application */
+
+SECTIONS
+{
+ .text : ALIGN(0x10)
+ {
+ KEEP (*(SORT_NONE(.text.entry)))
+ . = ALIGN(0x10);
+ *(.text .text.* .gnu.linkonce.t.*)
+ *(.plt)
+ . = ALIGN(0x10);
+
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*crtend.o(.ctors))
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*crtend.o(.dtors))
+
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.gcc_except_table)
+ *(.eh_frame_hdr)
+ *(.eh_frame)
+
+ KEEP (*(.init))
+ KEEP (*(.fini))
+
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ . = ALIGN(0x10);
+
+ } > ram
+
+ /* short/global data section */
+ .sdata : ALIGN(0x10)
+ {
+ __sdata_load = LOADADDR(.sdata);
+ __sdata_start = .;
+ PROVIDE( __global_pointer$ = . + 0x800);
+ *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2)
+ *(.srodata*)
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ . = ALIGN(0x10);
+ __sdata_end = .;
+ } > ram
+
+ /* data section */
+ .data : ALIGN(0x10)
+ {
+ __data_load = LOADADDR(.data);
+ __data_start = .;
+ *(.got.plt) *(.got)
+ *(.shdata)
+ *(.data .data.* .gnu.linkonce.d.*)
+ . = ALIGN(0x10);
+ __data_end = .;
+ } > ram
+
+ /* sbss section */
+ .sbss : ALIGN(0x10)
+ {
+ __sbss_start = .;
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ . = ALIGN(0x10);
+ __sbss_end = .;
+ } > ram
+
+ /* sbss section */
+ .bss : ALIGN(0x10)
+ {
+ __bss_start = .;
+ *(.shbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ . = ALIGN(0x10);
+ __bss_end = .;
+ } > ram
+
+ /* End of uninitialized data segment */
+ _end = .;
+
+ .heap : ALIGN(0x10)
+ {
+ __heap_start = .;
+ . += HEAP_SIZE;
+ __heap_end = .;
+ . = ALIGN(0x10);
+ _heap_end = __heap_end;
+ } > ram
+
+ .stack : ALIGN(0x10)
+ {
+ __stack_bottom = .;
+ . += STACK_SIZE;
+ __stack_top = .;
+ } > ram
+}
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.c
new file mode 100644
index 000000000..f7be82c09
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.c
@@ -0,0 +1,251 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file riscv_hal.c
+ * @author Microsemi SoC Products Group
+ * @brief Implementation of Hardware Abstraction Layer for Mi-V soft processors
+ *
+ * SVN $Revision: 9835 $
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
+ */
+#include
+#include
+#include
+
+#include "riscv_hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTC_PRESCALER 100UL
+
+#define SUCCESS 0U
+#define ERROR 1U
+
+/*------------------------------------------------------------------------------
+ *
+ */
+uint8_t Invalid_IRQHandler(void);
+uint8_t External_1_IRQHandler(void);
+uint8_t External_2_IRQHandler(void);
+uint8_t External_3_IRQHandler(void);
+uint8_t External_4_IRQHandler(void);
+uint8_t External_5_IRQHandler(void);
+uint8_t External_6_IRQHandler(void);
+uint8_t External_7_IRQHandler(void);
+uint8_t External_8_IRQHandler(void);
+uint8_t External_9_IRQHandler(void);
+uint8_t External_10_IRQHandler(void);
+uint8_t External_11_IRQHandler(void);
+uint8_t External_12_IRQHandler(void);
+uint8_t External_13_IRQHandler(void);
+uint8_t External_14_IRQHandler(void);
+uint8_t External_15_IRQHandler(void);
+uint8_t External_16_IRQHandler(void);
+uint8_t External_17_IRQHandler(void);
+uint8_t External_18_IRQHandler(void);
+uint8_t External_19_IRQHandler(void);
+uint8_t External_20_IRQHandler(void);
+uint8_t External_21_IRQHandler(void);
+uint8_t External_22_IRQHandler(void);
+uint8_t External_23_IRQHandler(void);
+uint8_t External_24_IRQHandler(void);
+uint8_t External_25_IRQHandler(void);
+uint8_t External_26_IRQHandler(void);
+uint8_t External_27_IRQHandler(void);
+uint8_t External_28_IRQHandler(void);
+uint8_t External_29_IRQHandler(void);
+uint8_t External_30_IRQHandler(void);
+uint8_t External_31_IRQHandler(void);
+
+/*------------------------------------------------------------------------------
+ *
+ */
+extern void Software_IRQHandler(void);
+
+/*------------------------------------------------------------------------------
+ * Increment value for the mtimecmp register in order to achieve a system tick
+ * interrupt as specified through the SysTick_Config() function.
+ */
+static uint64_t g_systick_increment = 0U;
+
+/*------------------------------------------------------------------------------
+ * Disable all interrupts.
+ */
+void __disable_irq(void)
+{
+ clear_csr(mstatus, MSTATUS_MPIE);
+ clear_csr(mstatus, MSTATUS_MIE);
+}
+
+/*------------------------------------------------------------------------------
+ * Enabler all interrupts.
+ */
+void __enable_irq(void)
+{
+ set_csr(mstatus, MSTATUS_MIE);
+}
+
+/*------------------------------------------------------------------------------
+ * Configure the machine timer to generate an interrupt.
+ */
+uint32_t SysTick_Config(uint32_t ticks)
+{
+ uint32_t ret_val = ERROR;
+
+ g_systick_increment = (uint64_t)(ticks) / RTC_PRESCALER;
+
+ if (g_systick_increment > 0U)
+ {
+ uint32_t mhart_id = read_csr(mhartid);
+
+ PRCI->MTIMECMP[mhart_id] = PRCI->MTIME + g_systick_increment;
+
+ set_csr(mie, MIP_MTIP);
+
+ __enable_irq();
+
+ ret_val = SUCCESS;
+ }
+
+ return ret_val;
+}
+
+/*------------------------------------------------------------------------------
+ * RISC-V interrupt handler for machine timer interrupts.
+ */
+static void handle_m_timer_interrupt(void)
+{
+ clear_csr(mie, MIP_MTIP);
+
+ SysTick_Handler();
+
+ PRCI->MTIMECMP[read_csr(mhartid)] = PRCI->MTIME + g_systick_increment;
+
+ set_csr(mie, MIP_MTIP);
+}
+
+/*------------------------------------------------------------------------------
+ * RISC-V interrupt handler for external interrupts.
+ */
+uint8_t (*ext_irq_handler_table[32])(void) =
+{
+ Invalid_IRQHandler,
+ External_1_IRQHandler,
+ External_2_IRQHandler,
+ External_3_IRQHandler,
+ External_4_IRQHandler,
+ External_5_IRQHandler,
+ External_6_IRQHandler,
+ External_7_IRQHandler,
+ External_8_IRQHandler,
+ External_9_IRQHandler,
+ External_10_IRQHandler,
+ External_11_IRQHandler,
+ External_12_IRQHandler,
+ External_13_IRQHandler,
+ External_14_IRQHandler,
+ External_15_IRQHandler,
+ External_16_IRQHandler,
+ External_17_IRQHandler,
+ External_18_IRQHandler,
+ External_19_IRQHandler,
+ External_20_IRQHandler,
+ External_21_IRQHandler,
+ External_22_IRQHandler,
+ External_23_IRQHandler,
+ External_24_IRQHandler,
+ External_25_IRQHandler,
+ External_26_IRQHandler,
+ External_27_IRQHandler,
+ External_28_IRQHandler,
+ External_29_IRQHandler,
+ External_30_IRQHandler,
+ External_31_IRQHandler
+};
+
+/*------------------------------------------------------------------------------
+ *
+ */
+static void handle_m_ext_interrupt(void)
+{
+ uint32_t int_num = PLIC_ClaimIRQ();
+ uint8_t disable = EXT_IRQ_KEEP_ENABLED;
+
+ disable = ext_irq_handler_table[int_num]();
+
+ PLIC_CompleteIRQ(int_num);
+
+ if(EXT_IRQ_DISABLE == disable)
+ {
+ PLIC_DisableIRQ((IRQn_Type)int_num);
+ }
+}
+
+static void handle_m_soft_interrupt(void)
+{
+ Software_IRQHandler();
+
+ /*Clear software interrupt*/
+ PRCI->MSIP[0] = 0x00U;
+}
+
+/*------------------------------------------------------------------------------
+ * Trap/Interrupt handler
+ */
+uintptr_t handle_trap(uintptr_t mcause, uintptr_t mepc)
+{
+ if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT))
+ {
+ handle_m_ext_interrupt();
+ }
+ else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER))
+ {
+ handle_m_timer_interrupt();
+ }
+ else if ( (mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_SOFT))
+ {
+ handle_m_soft_interrupt();
+ }
+ else
+ {
+#ifndef NDEBUG
+ /*
+ Arguments supplied to this function are mcause, mepc (exception PC) and stack pointer
+ based onprivileged-isa specification
+ mcause values and meanings are:
+ 0 Instruction address misaligned (mtval/mbadaddr is the address)
+ 1 Instruction access fault (mtval/mbadaddr is the address)
+ 2 Illegal instruction (mtval/mbadaddr contains the offending instruction opcode)
+ 3 Breakpoint
+ 4 Load address misaligned (mtval/mbadaddr is the address)
+ 5 Load address fault (mtval/mbadaddr is the address)
+ 6 Store/AMO address fault (mtval/mbadaddr is the address)
+ 7 Store/AMO access fault (mtval/mbadaddr is the address)
+ 8 Environment call from U-mode
+ 9 Environment call from S-mode
+ A Environment call from M-mode
+ B Instruction page fault
+ C Load page fault (mtval/mbadaddr is the address)
+ E Store page fault (mtval/mbadaddr is the address)
+ */
+
+ uintptr_t mip = read_csr(mip); /* interrupt pending */
+ uintptr_t mbadaddr = read_csr(mbadaddr); /* additional info and meaning depends on mcause */
+ uintptr_t mtvec = read_csr(mtvec); /* trap vector */
+ uintptr_t mscratch = read_csr(mscratch); /* temporary, sometimes might hold temporary value of a0 */
+ uintptr_t mstatus = read_csr(mstatus); /* status contains many smaller fields: */
+
+ /* breakpoint*/
+ __asm("ebreak");
+#else
+ _exit(1 + mcause);
+#endif
+ }
+ return mepc;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.h
new file mode 100644
index 000000000..7c3835fe3
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal.h
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file riscv_hal.h
+ * @author Microsemi SoC Products Group
+ * @brief Hardware Abstraction Layer functions for Mi-V soft processors
+ *
+ * SVN $Revision: 9835 $
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
+ */
+
+#ifndef RISCV_HAL_H
+#define RISCV_HAL_H
+
+#include "riscv_plic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ *Return value from External IRQ handler. This will be used to disable the External
+ *interrupt.
+ */
+#define EXT_IRQ_KEEP_ENABLED 0U
+#define EXT_IRQ_DISABLE 1U
+
+/*------------------------------------------------------------------------------
+ * Interrupt enable/disable.
+ */
+void __disable_irq(void);
+void __enable_irq(void);
+
+/*------------------------------------------------------------------------------
+ * System tick handler. This is generated from the RISC-V machine timer.
+ */
+void SysTick_Handler(void);
+
+/*------------------------------------------------------------------------------
+ * System tick configuration.
+ * Configures the machine timer to generate a system tick interrupt at regular
+ * intervals.
+ * Takes the number of system clock ticks between interrupts.
+ *
+ * Returns 0 if successful.
+ * Returns 1 if the interrupt interval cannot be achieved.
+ */
+uint32_t SysTick_Config(uint32_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_HAL_H */
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal_stubs.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal_stubs.c
new file mode 100644
index 000000000..29a4f407e
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_hal_stubs.c
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file riscv_hal_stubs.c
+ * @author Microsemi SoC Products Group
+ * @brief Mi-V soft processor Interrupt Function stubs.
+ * The functions below will only be linked with the application code if the user
+ * does not provide an implementation for these functions. These functions are
+ * defined with weak linking so that they can be overridden by a function with
+ * same prototype in the user's application code.
+ *
+ * SVN $Revision: 9835 $
+ * SVN $Date: 2018-03-19 19:11:35 +0530 (Mon, 19 Mar 2018) $
+ */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) void Software_IRQHandler(void)
+{
+ _exit(10);
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) void SysTick_Handler(void)
+{
+ /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t Invalid_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_1_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_2_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_3_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_4_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_5_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_6_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_7_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_8_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_9_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_10_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_11_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_12_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_13_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_14_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_15_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_16_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_17_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_18_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_19_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_20_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_21_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_22_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_23_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_24_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_25_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_26_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_27_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_28_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_29_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provided*/
+__attribute__((weak)) uint8_t External_30_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+/*Weakly linked handler. Will be replaced with user's definition if provide*/
+__attribute__((weak)) uint8_t External_31_IRQHandler(void)
+{
+ return(0U); /*Default handler*/
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_plic.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_plic.h
new file mode 100644
index 000000000..2d0951891
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/riscv_plic.h
@@ -0,0 +1,249 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file riscv_plic.h
+ * @author Microsemi SoC Products Group
+ * @brief Mi-V soft processor PLIC and PRCI access data structures and functions.
+ *
+ * SVN $Revision: 9838 $
+ * SVN $Date: 2018-03-19 19:22:54 +0530 (Mon, 19 Mar 2018) $
+ */
+#ifndef RISCV_PLIC_H
+#define RISCV_PLIC_H
+
+#include
+
+#include "encoding.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PLIC_NUM_SOURCES 31
+#define PLIC_NUM_PRIORITIES 0
+
+/*==============================================================================
+ * Interrupt numbers:
+ */
+typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ External_3_IRQn = 3,
+ External_4_IRQn = 4,
+ External_5_IRQn = 5,
+ External_6_IRQn = 6,
+ External_7_IRQn = 7,
+ External_8_IRQn = 8,
+ External_9_IRQn = 9,
+ External_10_IRQn = 10,
+ External_11_IRQn = 11,
+ External_12_IRQn = 12,
+ External_13_IRQn = 13,
+ External_14_IRQn = 14,
+ External_15_IRQn = 15,
+ External_16_IRQn = 16,
+ External_17_IRQn = 17,
+ External_18_IRQn = 18,
+ External_19_IRQn = 19,
+ External_20_IRQn = 20,
+ External_21_IRQn = 21,
+ External_22_IRQn = 22,
+ External_23_IRQn = 23,
+ External_24_IRQn = 24,
+ External_25_IRQn = 25,
+ External_26_IRQn = 26,
+ External_27_IRQn = 27,
+ External_28_IRQn = 28,
+ External_29_IRQn = 29,
+ External_30_IRQn = 30,
+ External_31_IRQn = 31
+} IRQn_Type;
+
+
+/*==============================================================================
+ * PLIC: Platform Level Interrupt Controller
+ */
+#define PLIC_BASE_ADDR 0x40000000UL
+
+typedef struct
+{
+ volatile uint32_t PRIORITY_THRESHOLD;
+ volatile uint32_t CLAIM_COMPLETE;
+ volatile uint32_t reserved[1022];
+} IRQ_Target_Type;
+
+typedef struct
+{
+ volatile uint32_t ENABLES[32];
+} Target_Enables_Type;
+
+typedef struct
+{
+ /*-------------------- Source Priority --------------------*/
+ volatile uint32_t SOURCE_PRIORITY[1024];
+
+ /*-------------------- Pending array --------------------*/
+ volatile const uint32_t PENDING_ARRAY[32];
+ volatile uint32_t RESERVED1[992];
+
+ /*-------------------- Target enables --------------------*/
+ volatile Target_Enables_Type TARGET_ENABLES[15808];
+
+ volatile uint32_t RESERVED2[16384];
+
+ /*--- Target Priority threshold and claim/complete---------*/
+ IRQ_Target_Type TARGET[15872];
+
+} PLIC_Type;
+
+
+#define PLIC ((PLIC_Type *)PLIC_BASE_ADDR)
+
+/*==============================================================================
+ * PRCI: Power, Reset, Clock, Interrupt
+ */
+#define PRCI_BASE 0x44000000UL
+
+typedef struct
+{
+ volatile uint32_t MSIP[4095];
+ volatile uint32_t reserved;
+ volatile uint64_t MTIMECMP[4095];
+ volatile const uint64_t MTIME;
+} PRCI_Type;
+
+#define PRCI ((PRCI_Type *)PRCI_BASE)
+
+/*==============================================================================
+ * The function PLIC_init() initializes the PLIC controller and enables the
+ * global external interrupt bit.
+ */
+static inline void PLIC_init(void)
+{
+ uint32_t inc;
+ unsigned long hart_id = read_csr(mhartid);
+
+ /* Disable all interrupts for the current hart. */
+ for(inc = 0; inc < ((PLIC_NUM_SOURCES + 32u) / 32u); ++inc)
+ {
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[inc] = 0;
+ }
+
+ /* Set priorities to zero. */
+ /* Should this really be done??? Calling PLIC_init() on one hart will cause
+ * the priorities previously set by other harts to be messed up. */
+ for(inc = 0; inc < PLIC_NUM_SOURCES; ++inc)
+ {
+ PLIC->SOURCE_PRIORITY[inc] = 0;
+ }
+
+ /* Set the threshold to zero. */
+ PLIC->TARGET[hart_id].PRIORITY_THRESHOLD = 0;
+
+ /* Enable machine external interrupts. */
+ set_csr(mie, MIP_MEIP);
+}
+
+/*==============================================================================
+ * The function PLIC_EnableIRQ() enables the external interrupt for the interrupt
+ * number indicated by the parameter IRQn.
+ */
+static inline void PLIC_EnableIRQ(IRQn_Type IRQn)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
+ current |= (uint32_t)1 << (IRQn % 32);
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
+}
+
+/*==============================================================================
+ * The function PLIC_DisableIRQ() disables the external interrupt for the interrupt
+ * number indicated by the parameter IRQn.
+
+ * NOTE:
+ * This function can be used to disable the external interrupt from outside
+ * external interrupt handler function.
+ * This function MUST NOT be used from within the External Interrupt handler.
+ * If you wish to disable the external interrupt while the interrupt handler
+ * for that external interrupt is executing then you must use the return value
+ * EXT_IRQ_DISABLE to return from the extern interrupt handler.
+ */
+static inline void PLIC_DisableIRQ(IRQn_Type IRQn)
+{
+ unsigned long hart_id = read_csr(mhartid);
+ uint32_t current = PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32];
+
+ current &= ~((uint32_t)1 << (IRQn % 32));
+
+ PLIC->TARGET_ENABLES[hart_id].ENABLES[IRQn / 32] = current;
+}
+
+/*==============================================================================
+ * The function PLIC_SetPriority() sets the priority for the external interrupt
+ * for the interrupt number indicated by the parameter IRQn.
+ */
+static inline void PLIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ PLIC->SOURCE_PRIORITY[IRQn] = priority;
+}
+
+/*==============================================================================
+ * The function PLIC_GetPriority() returns the priority for the external interrupt
+ * for the interrupt number indicated by the parameter IRQn.
+ */
+static inline uint32_t PLIC_GetPriority(IRQn_Type IRQn)
+{
+ return PLIC->SOURCE_PRIORITY[IRQn];
+}
+
+/*==============================================================================
+ * The function PLIC_ClaimIRQ() claims the interrupt from the PLIC controller.
+ */
+static inline uint32_t PLIC_ClaimIRQ(void)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ return PLIC->TARGET[hart_id].CLAIM_COMPLETE;
+}
+
+/*==============================================================================
+ * The function PLIC_CompleteIRQ() indicates to the PLIC controller the interrupt
+ * is processed and claim is complete.
+ */
+static inline void PLIC_CompleteIRQ(uint32_t source)
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ PLIC->TARGET[hart_id].CLAIM_COMPLETE = source;
+}
+
+/*==============================================================================
+ * The function raise_soft_interrupt() raises a synchronous software interrupt by
+ * writing into the MSIP register.
+ */
+static inline void raise_soft_interrupt()
+{
+ unsigned long hart_id = read_csr(mhartid);
+
+ /*You need to make sure that the global interrupt is enabled*/
+ set_csr(mie, MIP_MSIP); /*Enable software interrupt bit */
+ PRCI->MSIP[hart_id] = 0x01; /*raise soft interrupt for hart0*/
+}
+
+/*==============================================================================
+ * The function clear_soft_interrupt() clears a synchronous software interrupt by
+ * clearing the MSIP register.
+ */
+static inline void clear_soft_interrupt()
+{
+ unsigned long hart_id = read_csr(mhartid);
+ PRCI->MSIP[hart_id] = 0x00; /*clear soft interrupt for hart0*/
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RISCV_PLIC_H */
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/sample_hw_platform.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/sample_hw_platform.h
new file mode 100644
index 000000000..2990bd0c0
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/sample_hw_platform.h
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi Corporation. All rights reserved.
+ *
+ * Platform definitions
+ * Version based on requirements of RISCV-HAL
+ *
+ * SVN $Revision: 9946 $
+ * SVN $Date: 2018-04-30 20:26:55 +0530 (Mon, 30 Apr 2018) $
+ */
+ /*=========================================================================*//**
+ @mainpage Sample file detailing how hw_platform.h should be constructed for
+ the Mi-V processors.
+
+ @section intro_sec Introduction
+ The hw_platform.h is to be located in the project root directory.
+ Currently this file must be hand crafted when using the Mi-V Soft Processor.
+
+ You can use this file as sample.
+ Rename this file from sample_hw_platform.h to hw_platform.h and store it in
+ the root folder of your project. Then customize it per your HW design.
+
+ @section driver_configuration Project configuration Instructions
+ 1. Change SYS_CLK_FREQ define to frequency of Mi-V Soft processor clock
+ 2 Add all other core BASE addresses
+ 3. Add peripheral Core Interrupt to Mi-V Soft processor interrupt mappings
+ 4. Define MSCC_STDIO_UART_BASE_ADDR if you want a CoreUARTapb mapped to STDIO
+*//*=========================================================================*/
+
+#ifndef HW_PLATFORM_H
+#define HW_PLATFORM_H
+
+/***************************************************************************//**
+ * Soft-processor clock definition
+ * This is the only clock brought over from the Mi-V Soft processor Libero design.
+ */
+#ifndef SYS_CLK_FREQ
+#define SYS_CLK_FREQ 83000000UL
+#endif
+
+
+/***************************************************************************//**
+ * Non-memory Peripheral base addresses
+ * Format of define is:
+ * __BASE_ADDR
+ */
+#define COREUARTAPB0_BASE_ADDR 0x70001000UL
+#define COREGPIO_IN_BASE_ADDR 0x70002000UL
+#define CORETIMER0_BASE_ADDR 0x70003000UL
+#define CORETIMER1_BASE_ADDR 0x70004000UL
+#define COREGPIO_OUT_BASE_ADDR 0x70005000UL
+#define FLASH_CORE_SPI_BASE 0x70006000UL
+#define CORE16550_BASE_ADDR 0x70007000UL
+
+/***************************************************************************//**
+ * Peripheral Interrupts are mapped to the corresponding Mi-V Soft processor
+ * interrupt from the Libero design.
+ * There can be up to 31 external interrupts (IRQ[30:0] pins) on the Mi-V Soft
+ * processor.The Mi-V Soft processor external interrupts are defined in the
+ * riscv_plic.h
+ * These are of the form
+ * typedef enum
+{
+ NoInterrupt_IRQn = 0,
+ External_1_IRQn = 1,
+ External_2_IRQn = 2,
+ .
+ .
+ .
+ External_31_IRQn = 31
+} IRQn_Type;
+
+ The interrupt 0 on RISC-V processor is not used. The pin IRQ[0] should map to
+ External_1_IRQn likewise IRQ[30] should map to External_31_IRQn
+ * Format of define is:
+ * __
+ */
+
+#define TIMER0_IRQn External_30_IRQn
+#define TIMER1_IRQn External_31_IRQn
+
+/****************************************************************************
+ * Baud value to achieve a 115200 baud rate with a 83MHz system clock.
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+#define BAUD_VALUE_115200 (SYS_CLK_FREQ / (16 * 115200)) - 1
+
+/***************************************************************************//**
+ * User edit section- Edit sections below if required
+ */
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+/*
+ * A base address mapping for the STDIO printf/scanf mapping to CortUARTapb
+ * must be provided if it is being used
+ *
+ * e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+ */
+#define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB0_BASE_ADDR
+
+#ifndef MSCC_STDIO_UART_BASE_ADDR
+#error MSCC_STDIO_UART_BASE_ADDR not defined- e.g. #define MSCC_STDIO_UART_BASE_ADDR COREUARTAPB1_BASE_ADDR
+#endif
+
+#ifndef MSCC_STDIO_BAUD_VALUE
+/*
+ * The MSCC_STDIO_BAUD_VALUE define should be set in your project's settings to
+ * specify the baud value used by the standard output CoreUARTapb instance for
+ * generating the UART's baud rate if you want a different baud rate from the
+ * default of 115200 baud
+ */
+#define MSCC_STDIO_BAUD_VALUE 115200
+#endif /*MSCC_STDIO_BAUD_VALUE*/
+
+#endif /* end of MSCC_STDIO_THRU_CORE_UART_APB */
+/*******************************************************************************
+ * End of user edit section
+ */
+#endif /* HW_PLATFORM_H */
+
+
diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/syscall.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/syscall.c
new file mode 100644
index 000000000..4c99f8086
--- /dev/null
+++ b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/riscv_hal/syscall.c
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * (c) Copyright 2016-2018 Microsemi SoC Products Group. All rights reserved.
+ *
+ * @file syscall.c
+ * @author Microsemi SoC Products Group
+ * @brief Stubs for system calls.
+ *
+ * SVN $Revision: 9661 $
+ * SVN $Date: 2018-01-15 16:13:33 +0530 (Mon, 15 Jan 2018) $
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "encoding.h"
+
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+
+#include "core_uart_apb.h"
+#include "hw_platform.h"
+
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+
+/*------------------------------------------------------------------------------
+ * CoreUARTapb instance data for the CoreUARTapb instance used for standard
+ * output.
+ */
+static UART_instance_t g_stdio_uart;
+
+/*==============================================================================
+ * Flag used to indicate if the UART driver needs to be initialized.
+ */
+static int g_stdio_uart_init_done = 0;
+#endif /*MSCC_STDIO_THRU_CORE_UART_APB*/
+
+#undef errno
+int errno;
+
+char *__env[1] = { 0 };
+char **environ = __env;
+
+void write_hex(int fd, uint32_t hex)
+{
+ uint8_t ii;
+ uint8_t jj;
+ char towrite;
+ uint8_t digit;
+
+ write( fd , "0x", 2 );
+
+ for (ii = 8 ; ii > 0; ii--)
+ {
+ jj = ii-1;
+ digit = ((hex & (0xF << (jj*4))) >> (jj*4));
+ towrite = digit < 0xA ? ('0' + digit) : ('A' + (digit - 0xA));
+ write( fd, &towrite, 1);
+ }
+}
+
+
+void _exit(int code)
+{
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+ const char * message = "\nProgam has exited with code:";
+
+ write(STDERR_FILENO, message, strlen(message));
+ write_hex(STDERR_FILENO, code);
+#endif
+
+ while (1);
+}
+
+void *_sbrk(ptrdiff_t incr)
+{
+ extern char _end[];
+ extern char _heap_end[];
+ static char *curbrk = _end;
+
+ if ((curbrk + incr < _end) || (curbrk + incr > _heap_end))
+ {
+ return ((char *) - 1);
+ }
+
+ curbrk += incr;
+ return curbrk - incr;
+}
+
+int _isatty(int fd)
+{
+ if (fd == STDOUT_FILENO || fd == STDERR_FILENO)
+ {
+ return 1;
+ }
+
+ errno = EBADF;
+ return 0;
+}
+
+static int stub(int err)
+{
+ errno = err;
+ return -1;
+}
+
+int _open(const char* name, int flags, int mode)
+{
+ return stub(ENOENT);
+}
+
+int _openat(int dirfd, const char* name, int flags, int mode)
+{
+ return stub(ENOENT);
+}
+
+int _close(int fd)
+{
+ return stub(EBADF);
+}
+
+int _execve(const char* name, char* const argv[], char* const env[])
+{
+ return stub(ENOMEM);
+}
+
+int _fork()
+{
+ return stub(EAGAIN);
+}
+
+int _fstat(int fd, struct stat *st)
+{
+ if (isatty(fd))
+ {
+ st->st_mode = S_IFCHR;
+ return 0;
+ }
+
+ return stub(EBADF);
+}
+
+int _getpid()
+{
+ return 1;
+}
+
+int _kill(int pid, int sig)
+{
+ return stub(EINVAL);
+}
+
+int _link(const char *old_name, const char *new_name)
+{
+ return stub(EMLINK);
+}
+
+off_t _lseek(int fd, off_t ptr, int dir)
+{
+ if (_isatty(fd))
+ {
+ return 0;
+ }
+
+ return stub(EBADF);
+}
+
+ssize_t _read(int fd, void* ptr, size_t len)
+{
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+ if (_isatty(fd))
+ {
+ /*--------------------------------------------------------------------------
+ * Initialize the UART driver if it is the first time this function is
+ * called.
+ */
+ if ( !g_stdio_uart_init_done )
+ {
+ /******************************************************************************
+ * Baud value:
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));
+ g_stdio_uart_init_done = 1;
+ }
+
+ return UART_get_rx(&g_stdio_uart, (uint8_t*) ptr, len);
+ }
+#endif
+
+ return stub(EBADF);
+}
+
+int _stat(const char* file, struct stat* st)
+{
+ return stub(EACCES);
+}
+
+clock_t _times(struct tms* buf)
+{
+ return stub(EACCES);
+}
+
+int _unlink(const char* name)
+{
+ return stub(ENOENT);
+}
+
+int _wait(int* status)
+{
+ return stub(ECHILD);
+}
+
+ssize_t _write(int fd, const void* ptr, size_t len)
+{
+
+#ifdef MSCC_STDIO_THRU_CORE_UART_APB
+ const uint8_t * current = (const uint8_t *) ptr;
+ size_t jj;
+
+ if (_isatty(fd))
+ {
+ /*--------------------------------------------------------------------------
+ * Initialize the UART driver if it is the first time this function is
+ * called.
+ */
+ if ( !g_stdio_uart_init_done )
+ {
+ /******************************************************************************
+ * Baud value:
+ * This value is calculated using the following equation:
+ * BAUD_VALUE = (CLOCK / (16 * BAUD_RATE)) - 1
+ *****************************************************************************/
+ UART_init( &g_stdio_uart, MSCC_STDIO_UART_BASE_ADDR, ((SYS_CLK_FREQ/(16 * MSCC_STDIO_BAUD_VALUE))-1), (DATA_8_BITS | NO_PARITY));
+ g_stdio_uart_init_done = 1;
+ }
+
+ for (jj = 0; jj < len; jj++)
+ {
+ UART_send(&g_stdio_uart, current + jj, 1);
+ if (current[jj] == '\n')
+ {
+ UART_send(&g_stdio_uart, (const uint8_t *)"\r", 1);
+ }
+ }
+ return len;
+ }
+#endif
+
+ return stub(EBADF);
+}
+
+#ifdef __cplusplus
+}
+#endif