From: rtel Date: Mon, 24 Dec 2018 17:48:10 +0000 (+0000) Subject: Retarget Softconsole RISC-V demo from IGLOO2 to Renode as it can have more RAM and... X-Git-Tag: V10.2.0~31 X-Git-Url: https://git.sur5r.net/?p=freertos;a=commitdiff_plain;h=0d63fa4ced71b913de70aee4fea08d25c3a35511 Retarget Softconsole RISC-V demo from IGLOO2 to Renode as it can have more RAM and therefore have more test tasks running. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2611 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject deleted file mode 100644 index fd7ef95e1..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.cproject +++ /dev/null @@ -1,374 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project deleted file mode 100644 index 0e8872a4d..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.project +++ /dev/null @@ -1,237 +0,0 @@ - - - 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 - - - full_demo/common_demo_tasks - 2 - virtual:/virtual - - - full_demo/common_demo_tasks/AbortDelay.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/AbortDelay.c - - - full_demo/common_demo_tasks/EventGroupsDemo.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c - - - full_demo/common_demo_tasks/GenQTest.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/GenQTest.c - - - full_demo/common_demo_tasks/MessageBufferDemo.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c - - - full_demo/common_demo_tasks/StreamBufferDemo.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c - - - full_demo/common_demo_tasks/StreamBufferInterrupt.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c - - - full_demo/common_demo_tasks/TaskNotify.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/TaskNotify.c - - - full_demo/common_demo_tasks/TimerDemo.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/TimerDemo.c - - - full_demo/common_demo_tasks/blocktim.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/blocktim.c - - - full_demo/common_demo_tasks/countsem.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/countsem.c - - - full_demo/common_demo_tasks/death.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/death.c - - - full_demo/common_demo_tasks/dynamic.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/dynamic.c - - - full_demo/common_demo_tasks/include - 2 - FREERTOS_ROOT/FreeRTOS/Demo/Common/include - - - full_demo/common_demo_tasks/recmutex.c - 1 - FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/recmutex.c - - - - - 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 - - - - 1531000165521 - FreeRTOS_Source/portable - 9 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-GCC - - - - 1531000165526 - FreeRTOS_Source/portable - 9 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-MemMang - - - - 1531000203197 - FreeRTOS_Source/portable/GCC - 9 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-RISC-V-RV32 - - - - 1529524494421 - FreeRTOS_Source/portable/MemMang - 5 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-heap_4.c - - - - 1545005412575 - FreeRTOS_Source/portable/GCC/RISC-V-RV32 - 9 - - org.eclipse.ui.ide.multiFilter - 1.0-name-matches-false-false-CLINT_no_extensions - - - - - - 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 deleted file mode 100644 index f0af7e9d4..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/.settings/language.settings.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h deleted file mode 100644 index 08df67e18..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/FreeRTOSConfig.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - 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 - -#include "hw_platform.h" -#include "riscv_plic.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. - *----------------------------------------------------------*/ - -#define configCLINT_BASE_ADDRESS PRCI_BASE -#define configUSE_PREEMPTION 1 -#define configUSE_IDLE_HOOK 1 -#define configUSE_TICK_HOOK 1 -//#define configCPU_CLOCK_HZ ( ( unsigned long ) ( SYS_CLK_FREQ ) ) -#define configCPU_CLOCK_HZ ( ( unsigned long ) ( SYS_CLK_FREQ / 100 ) ) /*_RB_ Seems to be a factor of 100 between machine timer frequency and CPU frequency. */ -#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 150 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */ -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 280 * 1024 ) ) -#define configMAX_TASK_NAME_LEN ( 16 ) -#define configUSE_TRACE_FACILITY 0 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 0 -#define configUSE_MUTEXES 1 -#define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 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 1 -#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) -#define configTIMER_QUEUE_LENGTH 4 -#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 -#define INCLUDE_xTimerPendFunctionCall 1 -#define INCLUDE_xTaskAbortDelay 1 -#define INCLUDE_xTaskGetHandle 1 -#define INCLUDE_xSemaphoreGetMutexHolder 1 - -/* Normal assert() semantics without relying on the provision of an assert.h -header file. */ -#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); } - -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 - - -#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/Packages/.repos.xml b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/Packages/.repos.xml deleted file mode 100644 index 76dbb8968..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/Packages/.repos.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - CMSIS Pack - Keil - http://www.keil.com/pack/index.pidx - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core16550_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core16550_regs.h deleted file mode 100644 index 0b921ce74..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core16550_regs.h +++ /dev/null @@ -1,582 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/Core16550/core_16550.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.c deleted file mode 100644 index ca735e63a..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.c +++ /dev/null @@ -1,865 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/Core16550/core_16550.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.h deleted file mode 100644 index 98b1f16ea..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.h +++ /dev/null @@ -1,1264 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreGPIO/core_gpio.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.c deleted file mode 100644 index e5dbd7edf..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.c +++ /dev/null @@ -1,461 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreGPIO/core_gpio.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.h deleted file mode 100644 index 68799be27..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.h +++ /dev/null @@ -1,552 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreGPIO/coregpio_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/coregpio_regs.h deleted file mode 100644 index afbbfbcb8..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreGPIO/coregpio_regs.h +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreI2C/core_i2c.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.c deleted file mode 100644 index daa18879d..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.c +++ /dev/null @@ -1,1563 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreI2C/core_i2c.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.h deleted file mode 100644 index 2b1d5acab..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.h +++ /dev/null @@ -1,2280 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreI2C/core_smbus_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_smbus_regs.h deleted file mode 100644 index 67da7a5af..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_smbus_regs.h +++ /dev/null @@ -1,190 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreI2C/i2c_interrupt.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/i2c_interrupt.c deleted file mode 100644 index f918b8c9c..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreI2C/i2c_interrupt.c +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreTimer/core_timer.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.c deleted file mode 100644 index 3f6720b16..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.c +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreTimer/core_timer.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.h deleted file mode 100644 index 04b7a6e97..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.h +++ /dev/null @@ -1,206 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreTimer/coretimer_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/coretimer_regs.h deleted file mode 100644 index 5d7c67da2..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreTimer/coretimer_regs.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c deleted file mode 100644 index b4f40dc1e..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c +++ /dev/null @@ -1,296 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.h deleted file mode 100644 index 680b68d5b..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.h +++ /dev/null @@ -1,407 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/drivers/CoreUARTapb/coreuartapb_regs.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/coreuartapb_regs.h deleted file mode 100644 index e6cc8c1da..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/coreuartapb_regs.h +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/hal/cpu_types.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/cpu_types.h deleted file mode 100644 index 1beae8c96..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/cpu_types.h +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/hal/hal.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal.h deleted file mode 100644 index 5b82ed07d..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal.h +++ /dev/null @@ -1,207 +0,0 @@ -/***************************************************************************//** - * (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/Microsemi_Code/hal/hal_assert.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal_assert.h deleted file mode 100644 index db8ab7703..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal_assert.h +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/hal/hal_irq.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal_irq.c deleted file mode 100644 index 52f63016e..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hal_irq.c +++ /dev/null @@ -1,36 +0,0 @@ -/***************************************************************************//** - * (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/Microsemi_Code/hal/hw_macros.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_macros.h deleted file mode 100644 index 2149544ca..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_macros.h +++ /dev/null @@ -1,97 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/hal/hw_reg_access.S b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_reg_access.S deleted file mode 100644 index 68d93dd4c..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_reg_access.S +++ /dev/null @@ -1,209 +0,0 @@ -/***************************************************************************//** - * (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/Microsemi_Code/hal/hw_reg_access.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_reg_access.h deleted file mode 100644 index bc3dd654a..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/hal/hw_reg_access.h +++ /dev/null @@ -1,229 +0,0 @@ -/***************************************************************************//** - * (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/Microsemi_Code/riscv_hal/encoding.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/encoding.h deleted file mode 100644 index aa379ee5a..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/encoding.h +++ /dev/null @@ -1,596 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/riscv_hal/entry.S b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/entry.S deleted file mode 100644 index fce18d785..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/entry.S +++ /dev/null @@ -1,162 +0,0 @@ -/******************************************************************************* - * (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 - .extern vFreeRTOSPortTrapHandler - .globl _start - -_start: - j handle_reset - -nmi_vector: - j nmi_vector - -trap_vector: - j vFreeRTOSPortTrapHandler - -handle_reset: - la t0, vFreeRTOSPortTrapHandler - 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 - -#if 0 -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 /* 0 */ - -#endif - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/init.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/init.c deleted file mode 100644 index 8c5998f4d..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/init.c +++ /dev/null @@ -1,80 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld deleted file mode 100644 index 68d030d72..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * (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 = .; - _sp = .; - __freertos_irq_stack_top = .; - } > ram -} - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld deleted file mode 100644 index 305cb0ee6..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld +++ /dev/null @@ -1,139 +0,0 @@ -/******************************************************************************* - * (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 = .; - _sp = .; - __freertos_irq_stack_top = .; - } > ram -} - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c deleted file mode 100644 index 14ecf7bbe..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c +++ /dev/null @@ -1,130 +0,0 @@ -/******************************************************************************* - * (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" - -#include "FreeRTOS.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); -extern void Timer_IRQHandle( void ); - -/*------------------------------------------------------------------------------ - * 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 -}; - -/*------------------------------------------------------------------------------ - * - */ -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); - } -} - - -#ifdef __cplusplus -} -#endif diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.h deleted file mode 100644 index 7c3835fe3..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.h +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/riscv_hal/riscv_hal_stubs.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal_stubs.c deleted file mode 100644 index 29a4f407e..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal_stubs.c +++ /dev/null @@ -1,227 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/riscv_hal/riscv_plic.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_plic.h deleted file mode 100644 index 2d0951891..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/riscv_plic.h +++ /dev/null @@ -1,249 +0,0 @@ -/******************************************************************************* - * (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/Microsemi_Code/riscv_hal/sample_hw_platform.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/sample_hw_platform.h deleted file mode 100644 index d0604a1b0..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/sample_hw_platform.h +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * (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_BASE_ADDR 0x70002000UL -#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/Microsemi_Code/riscv_hal/syscall.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/syscall.c deleted file mode 100644 index 4c99f8086..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/Microsemi_Code/riscv_hal/syscall.c +++ /dev/null @@ -1,266 +0,0 @@ -/******************************************************************************* - * (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 diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Hardware.launch b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Hardware.launch deleted file mode 100644 index 64767a502..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Hardware.launch +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Renode.launch b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Renode.launch deleted file mode 100644 index 78d09056f..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug Renode.launch +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch deleted file mode 100644 index 9bc0bf0f3..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo Debug.launch +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch deleted file mode 100644 index 383dbed17..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/blinky_demo/main_blinky.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/blinky_demo/main_blinky.c deleted file mode 100644 index 7688ed8c7..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/blinky_demo/main_blinky.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -/****************************************************************************** - * NOTE 1: This project provides two demo applications. A simple blinky - * style project, and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select - * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY - * in main.c. This file implements the simply blinky style version. - * - * NOTE 2: This file only contains the source code that is specific to the - * basic demo. Generic functions, such FreeRTOS hook functions, and functions - * required to configure the hardware are defined in main.c. - ****************************************************************************** - * - * main_blinky() creates one queue, and two tasks. It then starts the - * scheduler. - * - * The Queue Send Task: - * The queue send task is implemented by the prvQueueSendTask() function in - * this file. prvQueueSendTask() sits in a loop that causes it to repeatedly - * block for 1000 milliseconds, before sending the value 100 to the queue that - * was created within main_blinky(). Once the value is sent, the task loops - * back around to block for another 1000 milliseconds...and so on. - * - * The Queue Receive Task: - * The queue receive task is implemented by the prvQueueReceiveTask() function - * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly - * blocks on attempts to read data from the queue that was created within - * main_blinky(). When data is received, the task checks the value of the - * data, and if the value equals the expected 100, writes 'Blink' to the UART - * (the UART is used in place of the LED to allow easy execution in QEMU). The - * 'block time' parameter passed to the queue receive function specifies that - * the task should be held in the Blocked state indefinitely to wait for data to - * be available on the queue. The queue receive task will only leave the - * Blocked state when the queue send task writes to the queue. As the queue - * send task writes to the queue every 1000 milliseconds, the queue receive - * task leaves the Blocked state every 1000 milliseconds, and therefore toggles - * the LED every 200 milliseconds. - */ - -/* Standard includes. */ -#include -#include -#include - -/* Kernel includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -/* Priorities used by the tasks. */ -#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) -#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) - -/* The rate at which data is sent to the queue. The 200ms value is converted -to ticks using the pdMS_TO_TICKS() macro. */ -#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 ) - -/* The maximum number items the queue can hold. The priority of the receiving -task is above the priority of the sending task, so the receiving task will -preempt the sending task and remove the queue items each time the sending task -writes to the queue. Therefore the queue will never have more than one item in -it at any time, and even with a queue length of 1, the sending task will never -find the queue full. */ -#define mainQUEUE_LENGTH ( 1 ) - -/*-----------------------------------------------------------*/ - -/* - * Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in - * main.c. - */ -void main_blinky( void ); - -/* - * The tasks as described in the comments at the top of this file. - */ -static void prvQueueReceiveTask( void *pvParameters ); -static void prvQueueSendTask( void *pvParameters ); - -/*-----------------------------------------------------------*/ - -/* The queue used by both tasks. */ -static QueueHandle_t xQueue = NULL; - -/*-----------------------------------------------------------*/ - -void main_blinky( void ) -{ - /* Create the queue. */ - xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) ); - - if( xQueue != NULL ) - { - /* Start the two tasks as described in the comments at the top of this - file. */ - xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ - "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ - configMINIMAL_STACK_SIZE * 2U, /* The size of the stack to allocate to the task. */ - NULL, /* The parameter passed to the task - not used in this case. */ - mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ - NULL ); /* The task handle is not required, so NULL is passed. */ - - xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL ); - - /* Start the tasks and timer running. */ - vTaskStartScheduler(); - } - - /* If all is well, the scheduler will now be running, and the following - line will never be reached. If the following line does execute, then - there was insufficient FreeRTOS heap memory available for the Idle and/or - timer tasks to be created. See the memory management section on the - FreeRTOS web site for more details on the FreeRTOS heap - http://www.freertos.org/a00111.html. */ - for( ;; ); -} -/*-----------------------------------------------------------*/ - -static void prvQueueSendTask( void *pvParameters ) -{ -TickType_t xNextWakeTime; -const unsigned long ulValueToSend = 100UL; -BaseType_t xReturned; - - /* Remove compiler warning about unused parameter. */ - ( void ) pvParameters; - - /* Initialise xNextWakeTime - this only needs to be done once. */ - xNextWakeTime = xTaskGetTickCount(); - - for( ;; ) - { - /* Place this task in the blocked state until it is time to run again. */ - vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); - - /* Send to the queue - causing the queue receive task to unblock and - toggle the LED. 0 is used as the block time so the sending operation - will not block - it shouldn't need to block as the queue should always - be empty at this point in the code. */ - xReturned = xQueueSend( xQueue, &ulValueToSend, 0U ); - configASSERT( xReturned == pdPASS ); - } -} -/*-----------------------------------------------------------*/ - -static void prvQueueReceiveTask( void *pvParameters ) -{ -unsigned long ulReceivedValue; -const unsigned long ulExpectedValue = 100UL; -const char * const pcPassMessage = "Blink\r\n"; -const char * const pcFailMessage = "Unexpected value received\r\n"; -extern void vSendString( const char * const pcString ); -extern void vToggleLED( void ); - - /* Remove compiler warning about unused parameter. */ - ( void ) pvParameters; - - for( ;; ) - { - /* Wait until something arrives in the queue - this task will block - indefinitely provided INCLUDE_vTaskSuspend is set to 1 in - FreeRTOSConfig.h. */ - xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); - - /* To get here something must have been received from the queue, but - is it the expected value? If it is, toggle the LED. */ - if( ulReceivedValue == ulExpectedValue ) - { - vSendString( pcPassMessage ); - vToggleLED(); - ulReceivedValue = 0U; - } - else - { - vSendString( pcFailMessage ); - } - } -} -/*-----------------------------------------------------------*/ - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/RegTest.S b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/RegTest.S deleted file mode 100644 index 702454f5d..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/RegTest.S +++ /dev/null @@ -1,260 +0,0 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - .extern ulRegTest1LoopCounter - .extern ulRegTest2LoopCounter - - .global vRegTest1Implementation - .global vRegTest2Implementation - -/*-----------------------------------------------------------*/ - -/* - * The register check tasks are described in the comments at the top of - * main_full.c. - */ - -vRegTest1Implementation: - - /* Fill the core registers with known values. */ - li x5, 0x5 - li x6, 0x6 - li x7, 0x7 - li x8, 0x8 - li x9, 0x9 - li x10, 0xa - li x11, 0xb - li x12, 0xc - li x13, 0xd - li x14, 0xe - li x15, 0xf - li x16, 0x10 - li x17, 0x11 - li x18, 0x12 - li x19, 0x13 - li x20, 0x14 - li x21, 0x15 - li x22, 0x16 - li x23, 0x17 - li x24, 0x18 - li x25, 0x19 - li x26, 0x1a - li x27, 0x1b - li x28, 0x1c - li x29, 0x1d - li x30, 0x1e - -reg1_loop: - - /* Check each register still contains the expected known value. - vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation - uses x5 as the temporary. */ - li x31, 0x5 - bne x31, x5, reg1_error_loop - li x31, 0x6 - bne x31, x6, reg1_error_loop - li x31, 0x7 - bne x31, x7, reg1_error_loop - li x31, 0x8 - bne x31, x8, reg1_error_loop - li x31, 0x9 - bne x31, x9, reg1_error_loop - li x31, 0xa - bne x31, x10, reg1_error_loop - li x31, 0xb - bne x31, x11, reg1_error_loop - li x31, 0xc - bne x31, x12, reg1_error_loop - li x31, 0xd - bne x31, x13, reg1_error_loop - li x31, 0xe - bne x31, x14, reg1_error_loop - li x31, 0xf - bne x31, x15, reg1_error_loop - li x31, 0x10 - bne x31, x16, reg1_error_loop - li x31, 0x11 - bne x31, x17, reg1_error_loop - li x31, 0x12 - bne x31, x18, reg1_error_loop - li x31, 0x13 - bne x31, x19, reg1_error_loop - li x31, 0x14 - bne x31, x20, reg1_error_loop - li x31, 0x15 - bne x31, x21, reg1_error_loop - li x31, 0x16 - bne x31, x22, reg1_error_loop - li x31, 0x17 - bne x31, x23, reg1_error_loop - li x31, 0x18 - bne x31, x24, reg1_error_loop - li x31, 0x19 - bne x31, x25, reg1_error_loop - li x31, 0x1a - bne x31, x26, reg1_error_loop - li x31, 0x1b - bne x31, x27, reg1_error_loop - li x31, 0x1c - bne x31, x28, reg1_error_loop - li x31, 0x1d - bne x31, x29, reg1_error_loop - li x31, 0x1e - bne x31, x30, reg1_error_loop - - /* Everything passed, increment the loop counter. */ - lw x31, ulRegTest1LoopCounterConst - lw x30, 0(x31) - addi x30, x30, 1 - sw x30, 0(x31) - - /* Restore clobbered register reading for next loop. */ - li x30, 0x1e - - /* Yield to increase code coverage. */ - ecall - - /* Start again. */ - jal reg1_loop - -reg1_error_loop: - /* Jump here if a register contains an uxpected value. This stops the loop - counter being incremented so the check task knows an error was found. */ - jal reg1_error_loop - -ulRegTest1LoopCounterConst: .word ulRegTest1LoopCounter - -/*-----------------------------------------------------------*/ - -vRegTest2Implementation: - - /* Fill the core registers with known values. */ - li x6, 0x61 - li x7, 0x71 - li x8, 0x81 - li x9, 0x91 - li x10, 0xa1 - li x11, 0xb1 - li x12, 0xc1 - li x13, 0xd1 - li x14, 0xe1 - li x15, 0xf1 - li x16, 0x20 - li x17, 0x21 - li x18, 0x22 - li x19, 0x23 - li x20, 0x24 - li x21, 0x25 - li x22, 0x26 - li x23, 0x27 - li x24, 0x28 - li x25, 0x29 - li x26, 0x2a - li x27, 0x2b - li x28, 0x2c - li x29, 0x2d - li x30, 0x2e - li x31, 0x2f - -Reg2_loop: - - /* Check each register still contains the expected known value. - vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation - uses x31 as the temporary. */ - li x5, 0x61 - bne x5, x6, reg2_error_loop - li x5, 0x71 - bne x5, x7, reg2_error_loop - li x5, 0x81 - bne x5, x8, reg2_error_loop - li x5, 0x91 - bne x5, x9, reg2_error_loop - li x5, 0xa1 - bne x5, x10, reg2_error_loop - li x5, 0xb1 - bne x5, x11, reg2_error_loop - li x5, 0xc1 - bne x5, x12, reg2_error_loop - li x5, 0xd1 - bne x5, x13, reg2_error_loop - li x5, 0xe1 - bne x5, x14, reg2_error_loop - li x5, 0xf1 - bne x5, x15, reg2_error_loop - li x5, 0x20 - bne x5, x16, reg2_error_loop - li x5, 0x21 - bne x5, x17, reg2_error_loop - li x5, 0x22 - bne x5, x18, reg2_error_loop - li x5, 0x23 - bne x5, x19, reg2_error_loop - li x5, 0x24 - bne x5, x20, reg2_error_loop - li x5, 0x25 - bne x5, x21, reg2_error_loop - li x5, 0x26 - bne x5, x22, reg2_error_loop - li x5, 0x27 - bne x5, x23, reg2_error_loop - li x5, 0x28 - bne x5, x24, reg2_error_loop - li x5, 0x29 - bne x5, x25, reg2_error_loop - li x5, 0x2a - bne x5, x26, reg2_error_loop - li x5, 0x2b - bne x5, x27, reg2_error_loop - li x5, 0x2c - bne x5, x28, reg2_error_loop - li x5, 0x2d - bne x5, x29, reg2_error_loop - li x5, 0x2e - bne x5, x30, reg2_error_loop - li x5, 0x2f - bne x5, x31, reg2_error_loop - - /* Everything passed, increment the loop counter. */ - lw x5, ulRegTest2LoopCounterConst - lw x6, 0(x5) - addi x6, x6, 1 - sw x6, 0(x5) - - /* Restore clobbered register reading for next loop. */ - li x6, 0x61 - - /* Start again. */ - jal Reg2_loop - -reg2_error_loop: - /* Jump here if a register contains an uxpected value. This stops the loop - counter being incremented so the check task knows an error was found. */ - jal reg2_error_loop - -ulRegTest2LoopCounterConst: .word ulRegTest2LoopCounter - - diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/main_full.c b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/main_full.c deleted file mode 100644 index f86b8c6a3..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/full_demo/main_full.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -/****************************************************************************** - * NOTE 1: This project provides two demo applications. A simple blinky style - * project, and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select - * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY - * in main.c. This file implements the comprehensive test and demo version. - * - * NOTE 2: This file only contains the source code that is specific to the - * full demo. Generic functions, such FreeRTOS hook functions, and functions - * required to configure the hardware, are defined in main.c. - * - ****************************************************************************** - * - * main_full() creates all the demo application tasks and software timers, then - * starts the scheduler. The web documentation provides more details of the - * standard demo application tasks, which provide no particular functionality, - * but do provide a good example of how to use the FreeRTOS API. - * - * In addition to the standard demo tasks, the following tasks and tests are - * defined and/or created within this file: - * - * "Reg test" tasks - These fill both the core registers with known values, then - * check that each register maintains its expected value for the lifetime of the - * task. Each task uses a different set of values. The reg test tasks execute - * with a very low priority, so get preempted very frequently. A register - * containing an unexpected value is indicative of an error in the context - * switching mechanism. - * - * "Check" task - The check executes every three seconds. It checks that all - * the standard demo tasks, and the register check tasks, are not only still - * executing, but are executing without reporting any errors. If the check task - * discovers that a task has either stalled, or reported an error, then it - * prints an error message to the UART, otherwise it prints "Pass.". - */ - -/* Standard includes. */ -#include -#include - -/* Kernel includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "timers.h" -#include "semphr.h" - -/* Microsemi incldues. */ -#include "core_timer.h" -#include "riscv_hal.h" - -/* Standard demo application includes. */ -#include "dynamic.h" -#include "blocktim.h" -#include "GenQTest.h" -#include "recmutex.h" -#include "TimerDemo.h" -#include "EventGroupsDemo.h" -#include "TaskNotify.h" -#include "AbortDelay.h" -#include "countsem.h" -#include "death.h" -#include "MessageBufferDemo.h" -#include "StreamBufferDemo.h" -#include "StreamBufferInterrupt.h" - -/* Priorities for the demo application tasks. */ -#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) -#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL ) - -/* The period of the check task, in ms, converted to ticks using the -pdMS_TO_TICKS() macro. mainNO_ERROR_CHECK_TASK_PERIOD is used if no errors have -been found, mainERROR_CHECK_TASK_PERIOD is used if an error has been found. */ -#define mainNO_ERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 3000UL ) -#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 500UL ) - -/* Parameters that are passed into the register check tasks solely for the -purpose of ensuring parameters are passed into tasks correctly. */ -#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 ) -#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 ) - -/* The base period used by the timer test tasks. */ -#define mainTIMER_TEST_PERIOD ( 50 ) - -/* The size of the stack allocated to the check task (as described in the -comments at the top of this file. */ -#define mainCHECK_TASK_STACK_SIZE_WORDS 100 - -/* Size of the stacks to allocated for the register check tasks. */ -#define mainREG_TEST_STACK_SIZE_WORDS 70 - -/*-----------------------------------------------------------*/ - -/* - * Called by main() to run the full demo (as opposed to the blinky demo) when - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. - */ -void main_full( void ); - -/* - * The check task, as described at the top of this file. - */ -static void prvCheckTask( void *pvParameters ); - -/* - * Initialise and start the peripheral timers that are used to exercise external - * interrupt processing. - */ -static void prvSetupPeripheralTimers( void ); - -/* - * Register check tasks as described at the top of this file. The nature of - * these files necessitates that they are written in an assembly file, but the - * entry points are kept in the C file for the convenience of checking the task - * parameter. - */ -static void prvRegTestTaskEntry1( void *pvParameters ); -extern void vRegTest1Implementation( void ); -static void prvRegTestTaskEntry2( void *pvParameters ); -extern void vRegTest2Implementation( void ); - -/* - * Tick hook used by the full demo, which includes code that interacts with - * some of the tests. - */ -void vFullDemoTickHook( void ); - -/*-----------------------------------------------------------*/ - -/* Timers used to exercise external interrupt processing. */ -static timer_instance_t g_timer0, g_timer1; - -/* Variables incremented by the peripheral timers used to exercise external -interrupts. */ -volatile uint32_t ulTimer0Interrupts = 0, ulTimer1Interrupts = 0; - -/* The following two variables are used to communicate the status of the -register check tasks to the check task. If the variables keep incrementing, -then the register check tasks have not discovered any errors. If a variable -stops incrementing, then an error has been found. */ -volatile uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL; - -/*-----------------------------------------------------------*/ - -void main_full( void ) -{ - /* Start all the other standard demo/test tasks. They have no particular - functionality, but do demonstrate how to use the FreeRTOS API and test the - kernel port. */ - vStartDynamicPriorityTasks(); - vCreateBlockTimeTasks(); - vStartGenericQueueTasks( tskIDLE_PRIORITY ); - vStartRecursiveMutexTasks(); - vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); - vStartEventGroupTasks(); - vStartTaskNotifyTask(); - vCreateAbortDelayTasks(); - vStartCountingSemaphoreTasks(); - vStartMessageBufferTasks( configMINIMAL_STACK_SIZE ); - vStartStreamBufferTasks(); - vStartStreamBufferInterruptDemo(); - - /* Create the register check tasks, as described at the top of this file. - Use xTaskCreateStatic() to create a task using only statically allocated - memory. */ - xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */ - "Reg1", /* The name of the task. */ - mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */ - mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */ - tskIDLE_PRIORITY, /* Priority of the task. */ - NULL ); /* Can be used to pass out a handle to the created task. */ - xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL ); - - /* Create the task that performs the 'check' functionality, as described at - the top of this file. */ - xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE_WORDS, NULL, mainCHECK_TASK_PRIORITY, NULL ); - - /* The set of tasks created by the following function call have to be - created last as they keep account of the number of tasks they expect to see - running. */ - vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); - - /* Start the timers that are used to exercise external interrupt handling. */ - prvSetupPeripheralTimers(); - - /* Start the scheduler. */ - vTaskStartScheduler(); - - /* If all is well, the scheduler will now be running, and the following - line will never be reached. If the following line does execute, then - there was insufficient FreeRTOS heap memory available for the Idle and/or - timer tasks to be created. See the memory management section on the - FreeRTOS web site for more details on the FreeRTOS heap - http://www.freertos.org/a00111.html. */ - for( ;; ); -} -/*-----------------------------------------------------------*/ - -static void prvCheckTask( void *pvParameters ) -{ -TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD; -TickType_t xLastExecutionTime; -uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0; -uint32_t ulLastTimer0Interrupts = 0, ulLastTimer1Interrupts = 0; -char * const pcPassMessage = "Pass.\r\n"; -char * pcStatusMessage = pcPassMessage; -extern void vSendString( const char * const pcString ); -extern void vToggleLED( void ); - - /* Just to stop compiler warnings. */ - ( void ) pvParameters; - - /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil() - works correctly. */ - xLastExecutionTime = xTaskGetTickCount(); - - /* Cycle for ever, delaying then checking all the other tasks are still - operating without error. The onboard LED is toggled on each iteration. - If an error is detected then the delay period is decreased from - mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the - effect of increasing the rate at which the onboard LED toggles, and in so - doing gives visual feedback of the system status. */ - for( ;; ) - { - /* Delay until it is time to execute again. */ - vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod ); - - /* Check all the demo tasks (other than the flash tasks) to ensure - that they are all still running, and that none have detected an error. */ - if( xAreDynamicPriorityTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Dynamic priority demo/tests.\r\n"; - } - - if ( xAreBlockTimeTestTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Block time demo/tests.\r\n"; - } - - if ( xAreGenericQueueTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Generic queue demo/tests.\r\n"; - } - - if ( xAreRecursiveMutexTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Recursive mutex demo/tests.\r\n"; - } - - if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) == pdFALSE ) - { - pcStatusMessage = "ERROR: Timer demo/tests.\r\n"; - } - - if( xAreEventGroupTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Event group demo/tests.\r\n"; - } - - if( xAreTaskNotificationTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Task notification demo/tests.\r\n"; - } - - if( xAreAbortDelayTestTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Abort delay.\r\n"; - } - - if( xAreCountingSemaphoreTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Counting semaphores.\r\n"; - } - - if( xIsCreateTaskStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Suicide tasks.\r\n"; - } - - if( xAreMessageBufferTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Message buffer.\r\n"; - } - - if( xAreStreamBufferTasksStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Stream buffer.\r\n"; - } - - if( xIsInterruptStreamBufferDemoStillRunning() == pdFALSE ) - { - pcStatusMessage = "ERROR: Stream buffer interrupt.\r\n"; - } - - /* Check that the register test 1 task is still running. */ - if( ulLastRegTest1Value == ulRegTest1LoopCounter ) - { - pcStatusMessage = "ERROR: Register test 1.\r\n"; - } - ulLastRegTest1Value = ulRegTest1LoopCounter; - - /* Check that the register test 2 task is still running. */ - if( ulLastRegTest2Value == ulRegTest2LoopCounter ) - { - pcStatusMessage = "ERROR: Register test 2.\r\n"; - } - ulLastRegTest2Value = ulRegTest2LoopCounter; - - /* Check interrupts from the peripheral timers are being handled. */ - if( ulLastTimer0Interrupts == ulTimer0Interrupts ) - { - pcStatusMessage = "ERROR: Peripheral timer 0.\r\n"; - } - ulLastTimer0Interrupts = ulTimer0Interrupts; - - if( ulLastTimer1Interrupts == ulTimer1Interrupts ) - { - pcStatusMessage = "ERROR: Peripheral timer 1.\r\n"; - } - ulLastTimer1Interrupts = ulTimer1Interrupts; - - /* Write the status message to the UART. */ - vSendString( pcStatusMessage ); - - /* If an error has been found then increase the LED toggle rate by - increasing the cycle frequency. */ - if( pcStatusMessage != pcPassMessage ) - { - xDelayPeriod = mainERROR_CHECK_TASK_PERIOD; - } - } -} -/*-----------------------------------------------------------*/ - -static void prvRegTestTaskEntry1( void *pvParameters ) -{ - /* Although the regtest task is written in assembler, its entry point is - written in C for convenience of checking the task parameter is being passed - in correctly. */ - if( pvParameters == mainREG_TEST_TASK_1_PARAMETER ) - { - /* Start the part of the test that is written in assembler. */ - vRegTest1Implementation(); - } - - /* The following line will only execute if the task parameter is found to - be incorrect. The check task will detect that the regtest loop counter is - not being incremented and flag an error. */ - vTaskDelete( NULL ); -} -/*-----------------------------------------------------------*/ - -static void prvRegTestTaskEntry2( void *pvParameters ) -{ - /* Although the regtest task is written in assembler, its entry point is - written in C for convenience of checking the task parameter is being passed - in correctly. */ - if( pvParameters == mainREG_TEST_TASK_2_PARAMETER ) - { - /* Start the part of the test that is written in assembler. */ - vRegTest2Implementation(); - } - - /* The following line will only execute if the task parameter is found to - be incorrect. The check task will detect that the regtest loop counter is - not being incremented and flag an error. */ - vTaskDelete( NULL ); -} -/*-----------------------------------------------------------*/ - -void vFullDemoTickHook( void ) -{ - /* The full demo includes a software timer demo/test that requires - prodding periodically from the tick interrupt. */ - vTimerPeriodicISRTests(); - - /* Call the periodic event group from ISR demo. */ - vPeriodicEventGroupsProcessing(); - - /* Use task notifications from an interrupt. */ - xNotifyTaskFromISR(); - - /* Writes to stream buffer byte by byte to test the stream buffer trigger - level functionality. */ - vPeriodicStreamBufferProcessing(); - - /* Writes a string to a string buffer four bytes at a time to demonstrate - a stream being sent from an interrupt to a task. */ - vBasicStreamBufferSendFromISR(); - - /* Called from vApplicationTickHook() when the project is configured to - build the full test/demo applications. */ -} -/*-----------------------------------------------------------*/ - -static void prvSetupPeripheralTimers( void ) -{ - TMR_init( &g_timer0, - CORETIMER0_BASE_ADDR, - TMR_CONTINUOUS_MODE, - PRESCALER_DIV_1024, - 83000 ); - - TMR_init( &g_timer1, - CORETIMER1_BASE_ADDR, - TMR_CONTINUOUS_MODE, - PRESCALER_DIV_512, - 42000 ); - - /* In this version of the PLIC, the priorities are fixed at 1. - Lower numbered devices have higher priorities. But this code is given as - an example. - */ - PLIC_SetPriority( External_30_IRQn, 1 ); - PLIC_SetPriority( External_31_IRQn, 1 ); - - /*Enable Timer 1 & 0 Interrupt*/ - PLIC_EnableIRQ( External_30_IRQn ); - PLIC_EnableIRQ( External_31_IRQn ); - - /* Enable the timers */ - TMR_enable_int( &g_timer0 ); - TMR_enable_int( &g_timer1 ); - - /* Make sure timers don't interrupt until the scheduler is running. */ - portDISABLE_INTERRUPTS(); - - /*Start the timer*/ - TMR_start( &g_timer0 ); - TMR_start( &g_timer1 ); -} -/*-----------------------------------------------------------*/ - -/*Core Timer 0 Interrupt Handler*/ -uint8_t External_30_IRQHandler( void ) -{ - ulTimer0Interrupts++; - TMR_clear_int(&g_timer0); - return( EXT_IRQ_KEEP_ENABLED ); -} -/*-----------------------------------------------------------*/ - -/*Core Timer 1 Interrupt Handler*/ -uint8_t External_31_IRQHandler( void ) -{ - ulTimer1Interrupts++; - TMR_clear_int(&g_timer1); - - return( EXT_IRQ_KEEP_ENABLED ); -} diff --git a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h b/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h deleted file mode 100644 index b56f10311..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/hw_platform.h +++ /dev/null @@ -1,119 +0,0 @@ -/******************************************************************************* - * (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 70000000UL -#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 deleted file mode 100644 index 59c3093f5..000000000 --- a/FreeRTOS/Demo/RISC-V_IGLOO2_Creative_SoftConsole/main.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * FreeRTOS Kernel V10.1.1 - * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -/* FreeRTOS kernel includes. */ -#include -#include - -/* Microsemi includes. */ -#include "core_uart_apb.h" -#include "core_gpio.h" - -/****************************************************************************** - * This project provides two demo applications. A simple blinky style project, - * and a more comprehensive test and demo application. The - * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to - * select between the two. The simply blinky demo is implemented and described - * in main_blinky.c. The more comprehensive test and demo application is - * implemented and described in main_full.c. - * - * This file implements the code that is not demo specific, including the - * hardware setup and standard FreeRTOS hook functions. - * - * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON - * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO - * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT! - * - */ - -/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo, -or 0 to run the more comprehensive test and demo application. */ -#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 - -/* - * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. - * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. - */ -#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 - extern void main_blinky( void ); -#else - extern void main_full( void ); -#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ - -/* Prototypes for the standard FreeRTOS callback/hook functions implemented -within this file. See https://www.freertos.org/a00016.html */ -void vApplicationMallocFailedHook( void ); -void vApplicationIdleHook( void ); -void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); -void vApplicationTickHook( void ); - -/* Prepare haredware to run the demo. */ -static void prvSetupHardware( void ); - -/* Send a messaage to the UART initialised in prvSetupHardware. */ -void vSendString( const char * const pcString ); - -/*-----------------------------------------------------------*/ - -/* The UART to which strings are output, and the GPIO used to toggle the LED. */ -static UART_instance_t g_uart; -static gpio_instance_t g_gpio_out; - -/*-----------------------------------------------------------*/ - -int main( void ) -{ - prvSetupHardware(); - - /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top - of this file. */ - #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) - { - main_blinky(); - } - #else - { - main_full(); - } - #endif -} -/*-----------------------------------------------------------*/ - -static void prvSetupHardware( void ) -{ - PLIC_init(); - UART_init( &g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200, ( DATA_8_BITS | NO_PARITY ) ); -} -/*-----------------------------------------------------------*/ - -void vToggleLED( void ) -{ -static uint32_t ulLEDState = 0; - - GPIO_set_outputs( &g_gpio_out, ulLEDState ); - ulLEDState = !ulLEDState; -} -/*-----------------------------------------------------------*/ - -void vSendString( const char * const pcString ) -{ - UART_polled_tx_string( &g_uart, pcString ); -} -/*-----------------------------------------------------------*/ - -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(); - __asm volatile( "ebreak" ); - 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(); - __asm volatile( "ebreak" ); - for( ;; ); -} -/*-----------------------------------------------------------*/ - -void vApplicationTickHook( void ) -{ - /* The tests in the full demo expect some interaction with interrupts. */ - #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) - { - extern void vFullDemoTickHook( void ); - vFullDemoTickHook(); - } - #endif -} - - diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.cproject b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.cproject new file mode 100644 index 000000000..af593fd3c --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.cproject @@ -0,0 +1,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.project b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.project new file mode 100644 index 000000000..0e8872a4d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.project @@ -0,0 +1,237 @@ + + + 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 + + + full_demo/common_demo_tasks + 2 + virtual:/virtual + + + full_demo/common_demo_tasks/AbortDelay.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/AbortDelay.c + + + full_demo/common_demo_tasks/EventGroupsDemo.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/EventGroupsDemo.c + + + full_demo/common_demo_tasks/GenQTest.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/GenQTest.c + + + full_demo/common_demo_tasks/MessageBufferDemo.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c + + + full_demo/common_demo_tasks/StreamBufferDemo.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/StreamBufferDemo.c + + + full_demo/common_demo_tasks/StreamBufferInterrupt.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/StreamBufferInterrupt.c + + + full_demo/common_demo_tasks/TaskNotify.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/TaskNotify.c + + + full_demo/common_demo_tasks/TimerDemo.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/TimerDemo.c + + + full_demo/common_demo_tasks/blocktim.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/blocktim.c + + + full_demo/common_demo_tasks/countsem.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/countsem.c + + + full_demo/common_demo_tasks/death.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/death.c + + + full_demo/common_demo_tasks/dynamic.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/dynamic.c + + + full_demo/common_demo_tasks/include + 2 + FREERTOS_ROOT/FreeRTOS/Demo/Common/include + + + full_demo/common_demo_tasks/recmutex.c + 1 + FREERTOS_ROOT/FreeRTOS/Demo/Common/Minimal/recmutex.c + + + + + 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 + + + + 1531000165521 + FreeRTOS_Source/portable + 9 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-GCC + + + + 1531000165526 + FreeRTOS_Source/portable + 9 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-MemMang + + + + 1531000203197 + FreeRTOS_Source/portable/GCC + 9 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-RISC-V-RV32 + + + + 1529524494421 + FreeRTOS_Source/portable/MemMang + 5 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-heap_4.c + + + + 1545005412575 + FreeRTOS_Source/portable/GCC/RISC-V-RV32 + 9 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-false-CLINT_no_extensions + + + + + + FREERTOS_ROOT + $%7BPARENT-3-PROJECT_LOC%7D + + + copy_PARENT + $%7BPARENT-4-PROJECT_LOC%7D/FreeRTOS/WorkingCopy/FreeRTOS + + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.settings/language.settings.xml b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.settings/language.settings.xml new file mode 100644 index 000000000..eb590e9ea --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/.settings/language.settings.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h new file mode 100644 index 000000000..40a7d8562 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/FreeRTOSConfig.h @@ -0,0 +1,148 @@ +/* + 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 + +#include "hw_platform.h" +#include "riscv_plic.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. + *----------------------------------------------------------*/ + +#define configCLINT_BASE_ADDRESS PRCI_BASE +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 1 +#define configCPU_CLOCK_HZ ( ( uint32_t ) ( SYS_CLK_FREQ ) ) +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configMAX_PRIORITIES ( 5 ) +#define configMINIMAL_STACK_SIZE ( ( uint32_t ) 170 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 280 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 16 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 8 +#define configCHECK_FOR_STACK_OVERFLOW 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 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 4 +#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 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 + +/* Normal assert() semantics without relying on the provision of an assert.h +header file. */ +#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); __asm volatile( "ebreak" ); for( ;; ); } + +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + + +#endif /* FREERTOS_CONFIG_H */ diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/Packages/.repos.xml b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/Packages/.repos.xml new file mode 100644 index 000000000..76dbb8968 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/Packages/.repos.xml @@ -0,0 +1,8 @@ + + + + CMSIS Pack + Keil + http://www.keil.com/pack/index.pidx + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core16550_regs.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core16550_regs.h new file mode 100644 index 000000000..0b921ce74 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.c new file mode 100644 index 000000000..ca735e63a --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/Core16550/core_16550.h new file mode 100644 index 000000000..98b1f16ea --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.c new file mode 100644 index 000000000..e5dbd7edf --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/core_gpio.h new file mode 100644 index 000000000..68799be27 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/coregpio_regs.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreGPIO/coregpio_regs.h new file mode 100644 index 000000000..afbbfbcb8 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.c new file mode 100644 index 000000000..daa18879d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_i2c.h new file mode 100644 index 000000000..2b1d5acab --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_smbus_regs.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/core_smbus_regs.h new file mode 100644 index 000000000..67da7a5af --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/i2c_interrupt.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreI2C/i2c_interrupt.c new file mode 100644 index 000000000..f918b8c9c --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.c new file mode 100644 index 000000000..3f6720b16 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/core_timer.h new file mode 100644 index 000000000..04b7a6e97 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/coretimer_regs.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreTimer/coretimer_regs.h new file mode 100644 index 000000000..5d7c67da2 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.c new file mode 100644 index 000000000..b4f40dc1e --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/core_uart_apb.h new file mode 100644 index 000000000..680b68d5b --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/coreuartapb_regs.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/drivers/CoreUARTapb/coreuartapb_regs.h new file mode 100644 index 000000000..e6cc8c1da --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/cpu_types.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/cpu_types.h new file mode 100644 index 000000000..1beae8c96 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal.h new file mode 100644 index 000000000..5b82ed07d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal_assert.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal_assert.h new file mode 100644 index 000000000..db8ab7703 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal_irq.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hal_irq.c new file mode 100644 index 000000000..52f63016e --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_macros.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_macros.h new file mode 100644 index 000000000..2149544ca --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_reg_access.S b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_reg_access.S new file mode 100644 index 000000000..68d93dd4c --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_reg_access.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/hal/hw_reg_access.h new file mode 100644 index 000000000..bc3dd654a --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/encoding.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/encoding.h new file mode 100644 index 000000000..aa379ee5a --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/entry.S b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/entry.S new file mode 100644 index 000000000..fce18d785 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/entry.S @@ -0,0 +1,162 @@ +/******************************************************************************* + * (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 + .extern vFreeRTOSPortTrapHandler + .globl _start + +_start: + j handle_reset + +nmi_vector: + j nmi_vector + +trap_vector: + j vFreeRTOSPortTrapHandler + +handle_reset: + la t0, vFreeRTOSPortTrapHandler + 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 + +#if 0 +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 /* 0 */ + +#endif + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/init.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/init.c new file mode 100644 index 000000000..8c5998f4d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld new file mode 100644 index 000000000..68d030d72 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-igloo2.ld @@ -0,0 +1,139 @@ +/******************************************************************************* + * (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 = .; + _sp = .; + __freertos_irq_stack_top = .; + } > ram +} + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld new file mode 100644 index 000000000..6b08b83a3 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/microsemi-riscv-ram.ld @@ -0,0 +1,139 @@ +/******************************************************************************* + * (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 = 2k; /* needs to be calculated for your application */ +HEAP_SIZE = 4; /* 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 = .; + _sp = .; + __freertos_irq_stack_top = .; + } > ram +} + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c new file mode 100644 index 000000000..14ecf7bbe --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.c @@ -0,0 +1,130 @@ +/******************************************************************************* + * (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" + +#include "FreeRTOS.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); +extern void Timer_IRQHandle( void ); + +/*------------------------------------------------------------------------------ + * 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 +}; + +/*------------------------------------------------------------------------------ + * + */ +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); + } +} + + +#ifdef __cplusplus +} +#endif diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal.h new file mode 100644 index 000000000..7c3835fe3 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal_stubs.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_hal_stubs.c new file mode 100644 index 000000000..29a4f407e --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_plic.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/riscv_plic.h new file mode 100644 index 000000000..2d0951891 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/sample_hw_platform.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/sample_hw_platform.h new file mode 100644 index 000000000..d0604a1b0 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/sample_hw_platform.h @@ -0,0 +1,121 @@ +/******************************************************************************* + * (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_BASE_ADDR 0x70002000UL +#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_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/syscall.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/riscv_hal/syscall.c new file mode 100644 index 000000000..4c99f8086 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/Microsemi_Code/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 diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch new file mode 100644 index 000000000..8f9f92c98 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo Debug Renode.launch @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch new file mode 100644 index 000000000..383dbed17 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/RTOSDemo-start-renode-emulator-and-attach.launch @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/blinky_demo/main_blinky.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/blinky_demo/main_blinky.c new file mode 100644 index 000000000..7688ed8c7 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/blinky_demo/main_blinky.c @@ -0,0 +1,206 @@ +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/****************************************************************************** + * NOTE 1: This project provides two demo applications. A simple blinky + * style project, and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select + * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY + * in main.c. This file implements the simply blinky style version. + * + * NOTE 2: This file only contains the source code that is specific to the + * basic demo. Generic functions, such FreeRTOS hook functions, and functions + * required to configure the hardware are defined in main.c. + ****************************************************************************** + * + * main_blinky() creates one queue, and two tasks. It then starts the + * scheduler. + * + * The Queue Send Task: + * The queue send task is implemented by the prvQueueSendTask() function in + * this file. prvQueueSendTask() sits in a loop that causes it to repeatedly + * block for 1000 milliseconds, before sending the value 100 to the queue that + * was created within main_blinky(). Once the value is sent, the task loops + * back around to block for another 1000 milliseconds...and so on. + * + * The Queue Receive Task: + * The queue receive task is implemented by the prvQueueReceiveTask() function + * in this file. prvQueueReceiveTask() sits in a loop where it repeatedly + * blocks on attempts to read data from the queue that was created within + * main_blinky(). When data is received, the task checks the value of the + * data, and if the value equals the expected 100, writes 'Blink' to the UART + * (the UART is used in place of the LED to allow easy execution in QEMU). The + * 'block time' parameter passed to the queue receive function specifies that + * the task should be held in the Blocked state indefinitely to wait for data to + * be available on the queue. The queue receive task will only leave the + * Blocked state when the queue send task writes to the queue. As the queue + * send task writes to the queue every 1000 milliseconds, the queue receive + * task leaves the Blocked state every 1000 milliseconds, and therefore toggles + * the LED every 200 milliseconds. + */ + +/* Standard includes. */ +#include +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +/* Priorities used by the tasks. */ +#define mainQUEUE_RECEIVE_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) +#define mainQUEUE_SEND_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 ) + +/* The rate at which data is sent to the queue. The 200ms value is converted +to ticks using the pdMS_TO_TICKS() macro. */ +#define mainQUEUE_SEND_FREQUENCY_MS pdMS_TO_TICKS( 1000 ) + +/* The maximum number items the queue can hold. The priority of the receiving +task is above the priority of the sending task, so the receiving task will +preempt the sending task and remove the queue items each time the sending task +writes to the queue. Therefore the queue will never have more than one item in +it at any time, and even with a queue length of 1, the sending task will never +find the queue full. */ +#define mainQUEUE_LENGTH ( 1 ) + +/*-----------------------------------------------------------*/ + +/* + * Called by main when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1 in + * main.c. + */ +void main_blinky( void ); + +/* + * The tasks as described in the comments at the top of this file. + */ +static void prvQueueReceiveTask( void *pvParameters ); +static void prvQueueSendTask( void *pvParameters ); + +/*-----------------------------------------------------------*/ + +/* The queue used by both tasks. */ +static QueueHandle_t xQueue = NULL; + +/*-----------------------------------------------------------*/ + +void main_blinky( void ) +{ + /* Create the queue. */ + xQueue = xQueueCreate( mainQUEUE_LENGTH, sizeof( uint32_t ) ); + + if( xQueue != NULL ) + { + /* Start the two tasks as described in the comments at the top of this + file. */ + xTaskCreate( prvQueueReceiveTask, /* The function that implements the task. */ + "Rx", /* The text name assigned to the task - for debug only as it is not used by the kernel. */ + configMINIMAL_STACK_SIZE * 2U, /* The size of the stack to allocate to the task. */ + NULL, /* The parameter passed to the task - not used in this case. */ + mainQUEUE_RECEIVE_TASK_PRIORITY, /* The priority assigned to the task. */ + NULL ); /* The task handle is not required, so NULL is passed. */ + + xTaskCreate( prvQueueSendTask, "TX", configMINIMAL_STACK_SIZE * 2U, NULL, mainQUEUE_SEND_TASK_PRIORITY, NULL ); + + /* Start the tasks and timer running. */ + vTaskStartScheduler(); + } + + /* If all is well, the scheduler will now be running, and the following + line will never be reached. If the following line does execute, then + there was insufficient FreeRTOS heap memory available for the Idle and/or + timer tasks to be created. See the memory management section on the + FreeRTOS web site for more details on the FreeRTOS heap + http://www.freertos.org/a00111.html. */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +static void prvQueueSendTask( void *pvParameters ) +{ +TickType_t xNextWakeTime; +const unsigned long ulValueToSend = 100UL; +BaseType_t xReturned; + + /* Remove compiler warning about unused parameter. */ + ( void ) pvParameters; + + /* Initialise xNextWakeTime - this only needs to be done once. */ + xNextWakeTime = xTaskGetTickCount(); + + for( ;; ) + { + /* Place this task in the blocked state until it is time to run again. */ + vTaskDelayUntil( &xNextWakeTime, mainQUEUE_SEND_FREQUENCY_MS ); + + /* Send to the queue - causing the queue receive task to unblock and + toggle the LED. 0 is used as the block time so the sending operation + will not block - it shouldn't need to block as the queue should always + be empty at this point in the code. */ + xReturned = xQueueSend( xQueue, &ulValueToSend, 0U ); + configASSERT( xReturned == pdPASS ); + } +} +/*-----------------------------------------------------------*/ + +static void prvQueueReceiveTask( void *pvParameters ) +{ +unsigned long ulReceivedValue; +const unsigned long ulExpectedValue = 100UL; +const char * const pcPassMessage = "Blink\r\n"; +const char * const pcFailMessage = "Unexpected value received\r\n"; +extern void vSendString( const char * const pcString ); +extern void vToggleLED( void ); + + /* Remove compiler warning about unused parameter. */ + ( void ) pvParameters; + + for( ;; ) + { + /* Wait until something arrives in the queue - this task will block + indefinitely provided INCLUDE_vTaskSuspend is set to 1 in + FreeRTOSConfig.h. */ + xQueueReceive( xQueue, &ulReceivedValue, portMAX_DELAY ); + + /* To get here something must have been received from the queue, but + is it the expected value? If it is, toggle the LED. */ + if( ulReceivedValue == ulExpectedValue ) + { + vSendString( pcPassMessage ); + vToggleLED(); + ulReceivedValue = 0U; + } + else + { + vSendString( pcFailMessage ); + } + } +} +/*-----------------------------------------------------------*/ + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/RegTest.S b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/RegTest.S new file mode 100644 index 000000000..702454f5d --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/RegTest.S @@ -0,0 +1,260 @@ +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + .extern ulRegTest1LoopCounter + .extern ulRegTest2LoopCounter + + .global vRegTest1Implementation + .global vRegTest2Implementation + +/*-----------------------------------------------------------*/ + +/* + * The register check tasks are described in the comments at the top of + * main_full.c. + */ + +vRegTest1Implementation: + + /* Fill the core registers with known values. */ + li x5, 0x5 + li x6, 0x6 + li x7, 0x7 + li x8, 0x8 + li x9, 0x9 + li x10, 0xa + li x11, 0xb + li x12, 0xc + li x13, 0xd + li x14, 0xe + li x15, 0xf + li x16, 0x10 + li x17, 0x11 + li x18, 0x12 + li x19, 0x13 + li x20, 0x14 + li x21, 0x15 + li x22, 0x16 + li x23, 0x17 + li x24, 0x18 + li x25, 0x19 + li x26, 0x1a + li x27, 0x1b + li x28, 0x1c + li x29, 0x1d + li x30, 0x1e + +reg1_loop: + + /* Check each register still contains the expected known value. + vRegTest1Implementation uses x31 as the temporary, vRegTest2Implementation + uses x5 as the temporary. */ + li x31, 0x5 + bne x31, x5, reg1_error_loop + li x31, 0x6 + bne x31, x6, reg1_error_loop + li x31, 0x7 + bne x31, x7, reg1_error_loop + li x31, 0x8 + bne x31, x8, reg1_error_loop + li x31, 0x9 + bne x31, x9, reg1_error_loop + li x31, 0xa + bne x31, x10, reg1_error_loop + li x31, 0xb + bne x31, x11, reg1_error_loop + li x31, 0xc + bne x31, x12, reg1_error_loop + li x31, 0xd + bne x31, x13, reg1_error_loop + li x31, 0xe + bne x31, x14, reg1_error_loop + li x31, 0xf + bne x31, x15, reg1_error_loop + li x31, 0x10 + bne x31, x16, reg1_error_loop + li x31, 0x11 + bne x31, x17, reg1_error_loop + li x31, 0x12 + bne x31, x18, reg1_error_loop + li x31, 0x13 + bne x31, x19, reg1_error_loop + li x31, 0x14 + bne x31, x20, reg1_error_loop + li x31, 0x15 + bne x31, x21, reg1_error_loop + li x31, 0x16 + bne x31, x22, reg1_error_loop + li x31, 0x17 + bne x31, x23, reg1_error_loop + li x31, 0x18 + bne x31, x24, reg1_error_loop + li x31, 0x19 + bne x31, x25, reg1_error_loop + li x31, 0x1a + bne x31, x26, reg1_error_loop + li x31, 0x1b + bne x31, x27, reg1_error_loop + li x31, 0x1c + bne x31, x28, reg1_error_loop + li x31, 0x1d + bne x31, x29, reg1_error_loop + li x31, 0x1e + bne x31, x30, reg1_error_loop + + /* Everything passed, increment the loop counter. */ + lw x31, ulRegTest1LoopCounterConst + lw x30, 0(x31) + addi x30, x30, 1 + sw x30, 0(x31) + + /* Restore clobbered register reading for next loop. */ + li x30, 0x1e + + /* Yield to increase code coverage. */ + ecall + + /* Start again. */ + jal reg1_loop + +reg1_error_loop: + /* Jump here if a register contains an uxpected value. This stops the loop + counter being incremented so the check task knows an error was found. */ + jal reg1_error_loop + +ulRegTest1LoopCounterConst: .word ulRegTest1LoopCounter + +/*-----------------------------------------------------------*/ + +vRegTest2Implementation: + + /* Fill the core registers with known values. */ + li x6, 0x61 + li x7, 0x71 + li x8, 0x81 + li x9, 0x91 + li x10, 0xa1 + li x11, 0xb1 + li x12, 0xc1 + li x13, 0xd1 + li x14, 0xe1 + li x15, 0xf1 + li x16, 0x20 + li x17, 0x21 + li x18, 0x22 + li x19, 0x23 + li x20, 0x24 + li x21, 0x25 + li x22, 0x26 + li x23, 0x27 + li x24, 0x28 + li x25, 0x29 + li x26, 0x2a + li x27, 0x2b + li x28, 0x2c + li x29, 0x2d + li x30, 0x2e + li x31, 0x2f + +Reg2_loop: + + /* Check each register still contains the expected known value. + vRegTest2Implementation uses x5 as the temporary, vRegTest1Implementation + uses x31 as the temporary. */ + li x5, 0x61 + bne x5, x6, reg2_error_loop + li x5, 0x71 + bne x5, x7, reg2_error_loop + li x5, 0x81 + bne x5, x8, reg2_error_loop + li x5, 0x91 + bne x5, x9, reg2_error_loop + li x5, 0xa1 + bne x5, x10, reg2_error_loop + li x5, 0xb1 + bne x5, x11, reg2_error_loop + li x5, 0xc1 + bne x5, x12, reg2_error_loop + li x5, 0xd1 + bne x5, x13, reg2_error_loop + li x5, 0xe1 + bne x5, x14, reg2_error_loop + li x5, 0xf1 + bne x5, x15, reg2_error_loop + li x5, 0x20 + bne x5, x16, reg2_error_loop + li x5, 0x21 + bne x5, x17, reg2_error_loop + li x5, 0x22 + bne x5, x18, reg2_error_loop + li x5, 0x23 + bne x5, x19, reg2_error_loop + li x5, 0x24 + bne x5, x20, reg2_error_loop + li x5, 0x25 + bne x5, x21, reg2_error_loop + li x5, 0x26 + bne x5, x22, reg2_error_loop + li x5, 0x27 + bne x5, x23, reg2_error_loop + li x5, 0x28 + bne x5, x24, reg2_error_loop + li x5, 0x29 + bne x5, x25, reg2_error_loop + li x5, 0x2a + bne x5, x26, reg2_error_loop + li x5, 0x2b + bne x5, x27, reg2_error_loop + li x5, 0x2c + bne x5, x28, reg2_error_loop + li x5, 0x2d + bne x5, x29, reg2_error_loop + li x5, 0x2e + bne x5, x30, reg2_error_loop + li x5, 0x2f + bne x5, x31, reg2_error_loop + + /* Everything passed, increment the loop counter. */ + lw x5, ulRegTest2LoopCounterConst + lw x6, 0(x5) + addi x6, x6, 1 + sw x6, 0(x5) + + /* Restore clobbered register reading for next loop. */ + li x6, 0x61 + + /* Start again. */ + jal Reg2_loop + +reg2_error_loop: + /* Jump here if a register contains an uxpected value. This stops the loop + counter being incremented so the check task knows an error was found. */ + jal reg2_error_loop + +ulRegTest2LoopCounterConst: .word ulRegTest2LoopCounter + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/main_full.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/main_full.c new file mode 100644 index 000000000..dc7d76863 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/full_demo/main_full.c @@ -0,0 +1,479 @@ +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/****************************************************************************** + * NOTE 1: This project provides two demo applications. A simple blinky style + * project, and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting in main.c is used to select + * between the two. See the notes on using mainCREATE_SIMPLE_BLINKY_DEMO_ONLY + * in main.c. This file implements the comprehensive test and demo version. + * + * NOTE 2: This file only contains the source code that is specific to the + * full demo. Generic functions, such FreeRTOS hook functions, and functions + * required to configure the hardware, are defined in main.c. + * + ****************************************************************************** + * + * main_full() creates all the demo application tasks and software timers, then + * starts the scheduler. The web documentation provides more details of the + * standard demo application tasks, which provide no particular functionality, + * but do provide a good example of how to use the FreeRTOS API. + * + * In addition to the standard demo tasks, the following tasks and tests are + * defined and/or created within this file: + * + * "Reg test" tasks - These fill both the core registers with known values, then + * check that each register maintains its expected value for the lifetime of the + * task. Each task uses a different set of values. The reg test tasks execute + * with a very low priority, so get preempted very frequently. A register + * containing an unexpected value is indicative of an error in the context + * switching mechanism. + * + * "Check" task - The check executes every three seconds. It checks that all + * the standard demo tasks, and the register check tasks, are not only still + * executing, but are executing without reporting any errors. If the check task + * discovers that a task has either stalled, or reported an error, then it + * prints an error message to the UART, otherwise it prints "Pass.". + */ + +/* Standard includes. */ +#include +#include + +/* Kernel includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "semphr.h" + +/* Microsemi incldues. */ +#include "core_timer.h" +#include "riscv_hal.h" + +/* Standard demo application includes. */ +#include "dynamic.h" +#include "blocktim.h" +#include "GenQTest.h" +#include "recmutex.h" +#include "TimerDemo.h" +#include "EventGroupsDemo.h" +#include "TaskNotify.h" +#include "AbortDelay.h" +#include "countsem.h" +#include "death.h" +#include "MessageBufferDemo.h" +#include "StreamBufferDemo.h" +#include "StreamBufferInterrupt.h" + +/* Priorities for the demo application tasks. */ +#define mainCHECK_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3UL ) + +/* The period of the check task, in ms, converted to ticks using the +pdMS_TO_TICKS() macro. mainNO_ERROR_CHECK_TASK_PERIOD is used if no errors have +been found, mainERROR_CHECK_TASK_PERIOD is used if an error has been found. */ +#define mainNO_ERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 3000UL ) +#define mainERROR_CHECK_TASK_PERIOD pdMS_TO_TICKS( 500UL ) + +/* Parameters that are passed into the register check tasks solely for the +purpose of ensuring parameters are passed into tasks correctly. */ +#define mainREG_TEST_TASK_1_PARAMETER ( ( void * ) 0x12345678 ) +#define mainREG_TEST_TASK_2_PARAMETER ( ( void * ) 0x87654321 ) + +/* The base period used by the timer test tasks. */ +#define mainTIMER_TEST_PERIOD ( 50 ) + +/* The size of the stack allocated to the check task (as described in the +comments at the top of this file. */ +#define mainCHECK_TASK_STACK_SIZE_WORDS 100 + +/* Size of the stacks to allocated for the register check tasks. */ +#define mainREG_TEST_STACK_SIZE_WORDS 70 + +/*-----------------------------------------------------------*/ + +/* + * Called by main() to run the full demo (as opposed to the blinky demo) when + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. + */ +void main_full( void ); + +/* + * The check task, as described at the top of this file. + */ +static void prvCheckTask( void *pvParameters ); + +/* + * Initialise and start the peripheral timers that are used to exercise external + * interrupt processing. + */ +static void prvSetupPeripheralTimers( void ); + +/* + * Register check tasks as described at the top of this file. The nature of + * these files necessitates that they are written in an assembly file, but the + * entry points are kept in the C file for the convenience of checking the task + * parameter. + */ +static void prvRegTestTaskEntry1( void *pvParameters ); +extern void vRegTest1Implementation( void ); +static void prvRegTestTaskEntry2( void *pvParameters ); +extern void vRegTest2Implementation( void ); + +/* + * Tick hook used by the full demo, which includes code that interacts with + * some of the tests. + */ +void vFullDemoTickHook( void ); + +/*-----------------------------------------------------------*/ + +/* Timers used to exercise external interrupt processing. */ +static timer_instance_t g_timer0, g_timer1; + +/* Variables incremented by the peripheral timers used to exercise external +interrupts. */ +volatile uint32_t ulTimer0Interrupts = 0, ulTimer1Interrupts = 0; + +/* The following two variables are used to communicate the status of the +register check tasks to the check task. If the variables keep incrementing, +then the register check tasks have not discovered any errors. If a variable +stops incrementing, then an error has been found. */ +volatile uint32_t ulRegTest1LoopCounter = 0UL, ulRegTest2LoopCounter = 0UL; + +/*-----------------------------------------------------------*/ + +void main_full( void ) +{ + /* Start all the other standard demo/test tasks. They have no particular + functionality, but do demonstrate how to use the FreeRTOS API and test the + kernel port. */ + vStartDynamicPriorityTasks(); + vCreateBlockTimeTasks(); + vStartGenericQueueTasks( tskIDLE_PRIORITY ); + vStartRecursiveMutexTasks(); + vStartTimerDemoTask( mainTIMER_TEST_PERIOD ); + vStartEventGroupTasks(); + vStartTaskNotifyTask(); + vCreateAbortDelayTasks(); + vStartCountingSemaphoreTasks(); + vStartMessageBufferTasks( configMINIMAL_STACK_SIZE ); + vStartStreamBufferTasks(); + vStartStreamBufferInterruptDemo(); + + /* Create the register check tasks, as described at the top of this file. + Use xTaskCreateStatic() to create a task using only statically allocated + memory. */ + xTaskCreate( prvRegTestTaskEntry1, /* The function that implements the task. */ + "Reg1", /* The name of the task. */ + mainREG_TEST_STACK_SIZE_WORDS, /* Size of stack to allocate for the task - in words not bytes!. */ + mainREG_TEST_TASK_1_PARAMETER, /* Parameter passed into the task. */ + tskIDLE_PRIORITY, /* Priority of the task. */ + NULL ); /* Can be used to pass out a handle to the created task. */ + xTaskCreate( prvRegTestTaskEntry2, "Reg2", mainREG_TEST_STACK_SIZE_WORDS, mainREG_TEST_TASK_2_PARAMETER, tskIDLE_PRIORITY, NULL ); + + /* Create the task that performs the 'check' functionality, as described at + the top of this file. */ + xTaskCreate( prvCheckTask, "Check", mainCHECK_TASK_STACK_SIZE_WORDS, NULL, mainCHECK_TASK_PRIORITY, NULL ); + + /* The set of tasks created by the following function call have to be + created last as they keep account of the number of tasks they expect to see + running. */ + vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + + /* Start the timers that are used to exercise external interrupt handling. */ + prvSetupPeripheralTimers(); + + /* Start the scheduler. */ + vTaskStartScheduler(); + + /* If all is well, the scheduler will now be running, and the following + line will never be reached. If the following line does execute, then + there was insufficient FreeRTOS heap memory available for the Idle and/or + timer tasks to be created. See the memory management section on the + FreeRTOS web site for more details on the FreeRTOS heap + http://www.freertos.org/a00111.html. */ + for( ;; ); +} +/*-----------------------------------------------------------*/ + +static void prvCheckTask( void *pvParameters ) +{ +TickType_t xDelayPeriod = mainNO_ERROR_CHECK_TASK_PERIOD; +TickType_t xLastExecutionTime; +uint32_t ulLastRegTest1Value = 0, ulLastRegTest2Value = 0; +uint32_t ulLastTimer0Interrupts = 0, ulLastTimer1Interrupts = 0; +char * const pcPassMessage = "."; +char * pcStatusMessage = pcPassMessage; +extern void vSendString( const char * const pcString ); +extern void vToggleLED( void ); + + /* Just to stop compiler warnings. */ + ( void ) pvParameters; + + /* Start with a pass message, after which a '.' character will be printed + out on each successful loop. */ + vSendString( "Pass" ); + + /* Initialise xLastExecutionTime so the first call to vTaskDelayUntil() + works correctly. */ + xLastExecutionTime = xTaskGetTickCount(); + + /* Cycle for ever, delaying then checking all the other tasks are still + operating without error. The onboard LED is toggled on each iteration. + If an error is detected then the delay period is decreased from + mainNO_ERROR_CHECK_TASK_PERIOD to mainERROR_CHECK_TASK_PERIOD. This has the + effect of increasing the rate at which the onboard LED toggles, and in so + doing gives visual feedback of the system status. */ + for( ;; ) + { + /* Delay until it is time to execute again. */ + vTaskDelayUntil( &xLastExecutionTime, xDelayPeriod ); + + /* Check all the demo tasks (other than the flash tasks) to ensure + that they are all still running, and that none have detected an error. */ + if( xAreDynamicPriorityTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Dynamic priority demo/tests.\r\n"; + } + + if ( xAreBlockTimeTestTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Block time demo/tests.\r\n"; + } + + if ( xAreGenericQueueTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Generic queue demo/tests.\r\n"; + } + + if ( xAreRecursiveMutexTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Recursive mutex demo/tests.\r\n"; + } + + if( xAreTimerDemoTasksStillRunning( ( TickType_t ) xDelayPeriod ) == pdFALSE ) + { + pcStatusMessage = "ERROR: Timer demo/tests.\r\n"; + } + + if( xAreEventGroupTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Event group demo/tests.\r\n"; + } + + if( xAreTaskNotificationTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Task notification demo/tests.\r\n"; + } + + if( xAreAbortDelayTestTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Abort delay.\r\n"; + } + + if( xAreCountingSemaphoreTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Counting semaphores.\r\n"; + } + + if( xIsCreateTaskStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Suicide tasks.\r\n"; + } + + if( xAreMessageBufferTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Message buffer.\r\n"; + } + + if( xAreStreamBufferTasksStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Stream buffer.\r\n"; + } + + if( xIsInterruptStreamBufferDemoStillRunning() == pdFALSE ) + { + pcStatusMessage = "ERROR: Stream buffer interrupt.\r\n"; + } + + /* Check that the register test 1 task is still running. */ + if( ulLastRegTest1Value == ulRegTest1LoopCounter ) + { + pcStatusMessage = "ERROR: Register test 1.\r\n"; + } + ulLastRegTest1Value = ulRegTest1LoopCounter; + + /* Check that the register test 2 task is still running. */ + if( ulLastRegTest2Value == ulRegTest2LoopCounter ) + { + pcStatusMessage = "ERROR: Register test 2.\r\n"; + } + ulLastRegTest2Value = ulRegTest2LoopCounter; + + /* Check interrupts from the peripheral timers are being handled. */ + if( ulLastTimer0Interrupts == ulTimer0Interrupts ) + { + pcStatusMessage = "ERROR: Peripheral timer 0.\r\n"; + } + ulLastTimer0Interrupts = ulTimer0Interrupts; + + if( ulLastTimer1Interrupts == ulTimer1Interrupts ) + { + pcStatusMessage = "ERROR: Peripheral timer 1.\r\n"; + } + ulLastTimer1Interrupts = ulTimer1Interrupts; + + /* Write the status message to the UART. */ + vSendString( pcStatusMessage ); + + /* If an error has been found then increase the LED toggle rate by + increasing the cycle frequency. */ + if( pcStatusMessage != pcPassMessage ) + { + xDelayPeriod = mainERROR_CHECK_TASK_PERIOD; + } + } +} +/*-----------------------------------------------------------*/ + +static void prvRegTestTaskEntry1( void *pvParameters ) +{ + /* Although the regtest task is written in assembler, its entry point is + written in C for convenience of checking the task parameter is being passed + in correctly. */ + if( pvParameters == mainREG_TEST_TASK_1_PARAMETER ) + { + /* Start the part of the test that is written in assembler. */ + vRegTest1Implementation(); + } + + /* The following line will only execute if the task parameter is found to + be incorrect. The check task will detect that the regtest loop counter is + not being incremented and flag an error. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +static void prvRegTestTaskEntry2( void *pvParameters ) +{ + /* Although the regtest task is written in assembler, its entry point is + written in C for convenience of checking the task parameter is being passed + in correctly. */ + if( pvParameters == mainREG_TEST_TASK_2_PARAMETER ) + { + /* Start the part of the test that is written in assembler. */ + vRegTest2Implementation(); + } + + /* The following line will only execute if the task parameter is found to + be incorrect. The check task will detect that the regtest loop counter is + not being incremented and flag an error. */ + vTaskDelete( NULL ); +} +/*-----------------------------------------------------------*/ + +void vFullDemoTickHook( void ) +{ + /* The full demo includes a software timer demo/test that requires + prodding periodically from the tick interrupt. */ + vTimerPeriodicISRTests(); + + /* Call the periodic event group from ISR demo. */ + vPeriodicEventGroupsProcessing(); + + /* Use task notifications from an interrupt. */ + xNotifyTaskFromISR(); + + /* Writes to stream buffer byte by byte to test the stream buffer trigger + level functionality. */ + vPeriodicStreamBufferProcessing(); + + /* Writes a string to a string buffer four bytes at a time to demonstrate + a stream being sent from an interrupt to a task. */ + vBasicStreamBufferSendFromISR(); + + /* Called from vApplicationTickHook() when the project is configured to + build the full test/demo applications. */ +} +/*-----------------------------------------------------------*/ + +static void prvSetupPeripheralTimers( void ) +{ + TMR_init( &g_timer0, + CORETIMER0_BASE_ADDR, + TMR_CONTINUOUS_MODE, + PRESCALER_DIV_1024, + 83000 ); + + TMR_init( &g_timer1, + CORETIMER1_BASE_ADDR, + TMR_CONTINUOUS_MODE, + PRESCALER_DIV_512, + 42000 ); + + /* In this version of the PLIC, the priorities are fixed at 1. + Lower numbered devices have higher priorities. But this code is given as + an example. + */ + PLIC_SetPriority( External_30_IRQn, 1 ); + PLIC_SetPriority( External_31_IRQn, 1 ); + + /*Enable Timer 1 & 0 Interrupt*/ + PLIC_EnableIRQ( External_30_IRQn ); + PLIC_EnableIRQ( External_31_IRQn ); + + /* Enable the timers */ + TMR_enable_int( &g_timer0 ); + TMR_enable_int( &g_timer1 ); + + /* Make sure timers don't interrupt until the scheduler is running. */ + portDISABLE_INTERRUPTS(); + + /*Start the timer*/ + TMR_start( &g_timer0 ); + TMR_start( &g_timer1 ); +} +/*-----------------------------------------------------------*/ + +/*Core Timer 0 Interrupt Handler*/ +uint8_t External_30_IRQHandler( void ) +{ + ulTimer0Interrupts++; + TMR_clear_int(&g_timer0); + return( EXT_IRQ_KEEP_ENABLED ); +} +/*-----------------------------------------------------------*/ + +/*Core Timer 1 Interrupt Handler*/ +uint8_t External_31_IRQHandler( void ) +{ + ulTimer1Interrupts++; + TMR_clear_int(&g_timer1); + + return( EXT_IRQ_KEEP_ENABLED ); +} diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/hw_platform.h b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/hw_platform.h new file mode 100644 index 000000000..b56f10311 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_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 70000000UL +#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_Renode_Emulator_SoftConsole/main.c b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/main.c new file mode 100644 index 000000000..59c3093f5 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/main.c @@ -0,0 +1,185 @@ +/* + * FreeRTOS Kernel V10.1.1 + * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/* FreeRTOS kernel includes. */ +#include +#include + +/* Microsemi includes. */ +#include "core_uart_apb.h" +#include "core_gpio.h" + +/****************************************************************************** + * This project provides two demo applications. A simple blinky style project, + * and a more comprehensive test and demo application. The + * mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting (defined in this file) is used to + * select between the two. The simply blinky demo is implemented and described + * in main_blinky.c. The more comprehensive test and demo application is + * implemented and described in main_full.c. + * + * This file implements the code that is not demo specific, including the + * hardware setup and standard FreeRTOS hook functions. + * + * ENSURE TO READ THE DOCUMENTATION PAGE FOR THIS PORT AND DEMO APPLICATION ON + * THE http://www.FreeRTOS.org WEB SITE FOR FULL INFORMATION ON USING THIS DEMO + * APPLICATION, AND ITS ASSOCIATE FreeRTOS ARCHITECTURE PORT! + * + */ + +/* Set mainCREATE_SIMPLE_BLINKY_DEMO_ONLY to one to run the simple blinky demo, +or 0 to run the more comprehensive test and demo application. */ +#define mainCREATE_SIMPLE_BLINKY_DEMO_ONLY 0 + +/* + * main_blinky() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 1. + * main_full() is used when mainCREATE_SIMPLE_BLINKY_DEMO_ONLY is set to 0. + */ +#if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 + extern void main_blinky( void ); +#else + extern void main_full( void ); +#endif /* #if mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 */ + +/* Prototypes for the standard FreeRTOS callback/hook functions implemented +within this file. See https://www.freertos.org/a00016.html */ +void vApplicationMallocFailedHook( void ); +void vApplicationIdleHook( void ); +void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ); +void vApplicationTickHook( void ); + +/* Prepare haredware to run the demo. */ +static void prvSetupHardware( void ); + +/* Send a messaage to the UART initialised in prvSetupHardware. */ +void vSendString( const char * const pcString ); + +/*-----------------------------------------------------------*/ + +/* The UART to which strings are output, and the GPIO used to toggle the LED. */ +static UART_instance_t g_uart; +static gpio_instance_t g_gpio_out; + +/*-----------------------------------------------------------*/ + +int main( void ) +{ + prvSetupHardware(); + + /* The mainCREATE_SIMPLE_BLINKY_DEMO_ONLY setting is described at the top + of this file. */ + #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY == 1 ) + { + main_blinky(); + } + #else + { + main_full(); + } + #endif +} +/*-----------------------------------------------------------*/ + +static void prvSetupHardware( void ) +{ + PLIC_init(); + UART_init( &g_uart, COREUARTAPB0_BASE_ADDR, BAUD_VALUE_115200, ( DATA_8_BITS | NO_PARITY ) ); +} +/*-----------------------------------------------------------*/ + +void vToggleLED( void ) +{ +static uint32_t ulLEDState = 0; + + GPIO_set_outputs( &g_gpio_out, ulLEDState ); + ulLEDState = !ulLEDState; +} +/*-----------------------------------------------------------*/ + +void vSendString( const char * const pcString ) +{ + UART_polled_tx_string( &g_uart, pcString ); +} +/*-----------------------------------------------------------*/ + +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(); + __asm volatile( "ebreak" ); + 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(); + __asm volatile( "ebreak" ); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ + /* The tests in the full demo expect some interaction with interrupts. */ + #if( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) + { + extern void vFullDemoTickHook( void ); + vFullDemoTickHook(); + } + #endif +} + + diff --git a/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/microsemi-riscv-renode.ld b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/microsemi-riscv-renode.ld new file mode 100644 index 000000000..6b08b83a3 --- /dev/null +++ b/FreeRTOS/Demo/RISC-V_Renode_Emulator_SoftConsole/microsemi-riscv-renode.ld @@ -0,0 +1,139 @@ +/******************************************************************************* + * (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 = 2k; /* needs to be calculated for your application */ +HEAP_SIZE = 4; /* 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 = .; + _sp = .; + __freertos_irq_stack_top = .; + } > ram +} +